Merge inbound to mozilla-central. a=merge
authorBogdan Tara <btara@mozilla.com>
Sun, 31 Mar 2019 12:00:08 +0300
changeset 466998 c06dfc552c647a6ce96f35cd84c32a589dc85608
parent 466960 9b129ff965d75b364c9bdb4d737542cb4d1c40d1 (current diff)
parent 466997 df0decf794e26365a9a8a366952686fc21593ce8 (diff)
child 467000 e5a4f263f3a00348bd49fe0dfddb0dbdf8ea3bab
child 467005 bdc95cb6984914763304589aebd718c8da260351
push id35789
push userbtara@mozilla.com
push dateSun, 31 Mar 2019 09:00:52 +0000
treeherdermozilla-central@c06dfc552c64 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
c06dfc552c64 / 68.0a1 / 20190331090052 / files
nightly linux64
c06dfc552c64 / 68.0a1 / 20190331090052 / files
nightly mac
c06dfc552c64 / 68.0a1 / 20190331090052 / files
nightly win32
c06dfc552c64 / 68.0a1 / 20190331090052 / files
nightly win64
c06dfc552c64 / 68.0a1 / 20190331090052 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
browser/base/content/defaultthemes/dark.icon.svg
browser/base/content/defaultthemes/light.icon.svg
browser/tools/mozscreenshots/mozscreenshots/extension/lib/black_theme.png
browser/tools/mozscreenshots/mozscreenshots/extension/lib/white_theme.png
gfx/skia/skia/include/core/SkLights.h
gfx/skia/skia/include/core/SkMetaData.h
gfx/skia/skia/include/core/SkYUVSizeInfo.h
gfx/skia/skia/include/gpu/GrResourceKey.h
gfx/skia/skia/include/gpu/vk/GrVkDefines.h
gfx/skia/skia/include/private/SkAtomics.h
gfx/skia/skia/src/codec/SkRawAdapterCodec.cpp
gfx/skia/skia/src/codec/SkRawAdapterCodec.h
gfx/skia/skia/src/codec/SkWebpAdapterCodec.cpp
gfx/skia/skia/src/codec/SkWebpAdapterCodec.h
gfx/skia/skia/src/core/Sk4x4f.h
gfx/skia/skia/src/core/SkBitmapProcState_filter.h
gfx/skia/skia/src/core/SkBitmapProcState_matrix.h
gfx/skia/skia/src/core/SkBitmapProcState_matrix_template.h
gfx/skia/skia/src/core/SkBitmapProcState_procs.h
gfx/skia/skia/src/core/SkBitmapProcState_sample.h
gfx/skia/skia/src/core/SkBitmapProcState_shaderproc.h
gfx/skia/skia/src/core/SkBitmapProcState_utils.h
gfx/skia/skia/src/core/SkBlitMask.h
gfx/skia/skia/src/core/SkBlitMask_D32.cpp
gfx/skia/skia/src/core/SkColorData.h
gfx/skia/skia/src/core/SkCubicMap.h
gfx/skia/skia/src/core/SkDeduper.h
gfx/skia/skia/src/core/SkFDot6Constants.cpp
gfx/skia/skia/src/core/SkFDot6Constants.h
gfx/skia/skia/src/core/SkFlattenablePriv.h
gfx/skia/skia/src/core/SkGlyphCache.cpp
gfx/skia/skia/src/core/SkGlyphCache.h
gfx/skia/skia/src/core/SkHalf.h
gfx/skia/skia/src/core/SkLights.cpp
gfx/skia/skia/src/core/SkMetaData.cpp
gfx/skia/skia/src/core/SkNx.h
gfx/skia/skia/src/core/SkPM4f.h
gfx/skia/skia/src/core/SkPM4fPriv.h
gfx/skia/skia/src/core/SkPaint_text.cpp
gfx/skia/skia/src/core/SkPictureImageGenerator.h
gfx/skia/skia/src/core/SkUnPreMultiplyPriv.h
gfx/skia/skia/src/core/SkUtilsArm.h
gfx/skia/skia/src/gpu/GrBuffer.cpp
gfx/skia/skia/src/gpu/GrDirectContext.cpp
gfx/skia/skia/src/gpu/GrUninstantiateProxyTracker.cpp
gfx/skia/skia/src/gpu/GrUninstantiateProxyTracker.h
gfx/skia/skia/src/gpu/ops/GrAAFillRectOp.cpp
gfx/skia/skia/src/gpu/ops/GrAAStrokeRectOp.cpp
gfx/skia/skia/src/gpu/ops/GrNonAAFillRectOp.cpp
gfx/skia/skia/src/gpu/ops/GrNonAAStrokeRectOp.cpp
gfx/skia/skia/src/gpu/ops/GrRectOpFactory.h
gfx/skia/skia/src/gpu/text/GrGlyphCache.cpp
gfx/skia/skia/src/gpu/text/GrGlyphCache.h
gfx/skia/skia/src/jumper/SkJumper.cpp
gfx/skia/skia/src/jumper/SkJumper.h
gfx/skia/skia/src/jumper/SkJumper_misc.h
gfx/skia/skia/src/opts/SkBitmapProcState_arm_neon.cpp
gfx/skia/skia/src/opts/SkBitmapProcState_filter_neon.h
gfx/skia/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp
gfx/skia/skia/src/opts/SkBitmapProcState_matrix_neon.h
gfx/skia/skia/src/opts/SkBitmapProcState_opts_SSE2.cpp
gfx/skia/skia/src/opts/SkBitmapProcState_opts_SSE2.h
gfx/skia/skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp
gfx/skia/skia/src/opts/SkBitmapProcState_opts_SSSE3.h
gfx/skia/skia/src/opts/SkBitmapProcState_opts_none.cpp
gfx/skia/skia/src/opts/SkBlitMask_opts_arm.cpp
gfx/skia/skia/src/opts/SkBlitMask_opts_arm_neon.cpp
gfx/skia/skia/src/opts/SkBlitMask_opts_arm_neon.h
gfx/skia/skia/src/opts/SkBlitMask_opts_none.cpp
gfx/skia/skia/src/opts/SkBlitRow_opts_SSE2.cpp
gfx/skia/skia/src/opts/SkBlitRow_opts_SSE2.h
gfx/skia/skia/src/opts/SkBlitRow_opts_arm.cpp
gfx/skia/skia/src/opts/SkBlitRow_opts_arm_neon.cpp
gfx/skia/skia/src/opts/SkBlitRow_opts_arm_neon.h
gfx/skia/skia/src/opts/SkBlitRow_opts_none.cpp
gfx/skia/skia/src/opts/SkColor_opts_SSE2.h
gfx/skia/skia/src/opts/SkColor_opts_neon.h
gfx/skia/skia/src/opts/SkMorphologyImageFilter_opts.h
gfx/skia/skia/src/opts/SkNx_neon.h
gfx/skia/skia/src/opts/SkNx_sse.h
gfx/skia/skia/src/opts/opts_check_x86.cpp
gfx/skia/skia/src/pathops/SkPathOpsPoint.cpp
gfx/skia/skia/src/pdf/SkPDFCanon.cpp
gfx/skia/skia/src/pdf/SkPDFCanon.h
gfx/skia/skia/src/ports/SkGlobalInitialization_default_imagefilters.cpp
gfx/skia/skia/src/ports/SkGlobalInitialization_none.cpp
gfx/skia/skia/src/ports/SkGlobalInitialization_none_imagefilters.cpp
gfx/skia/skia/third_party/vulkan/LICENSE
gfx/skia/skia/third_party/vulkan/SkiaVulkan.h
gfx/skia/skia/third_party/vulkan/vulkan/vk_platform.h
gfx/skia/skia/third_party/vulkan/vulkan/vulkan.h
gfx/skia/skia/third_party/vulkan/vulkan/vulkan_android.h
gfx/skia/skia/third_party/vulkan/vulkan/vulkan_core.h
gfx/skia/skia/third_party/vulkan/vulkan/vulkan_ios.h
gfx/skia/skia/third_party/vulkan/vulkan/vulkan_macos.h
gfx/skia/skia/third_party/vulkan/vulkan/vulkan_win32.h
gfx/skia/skia/third_party/vulkan/vulkan/vulkan_xcb.h
testing/mochitest/install.rdf
testing/web-platform/meta/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fill.html.ini
testing/web-platform/meta/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillRect.html.ini
testing/web-platform/meta/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillText.html.ini
testing/web-platform/meta/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.stroke.html.ini
testing/web-platform/meta/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeRect.html.ini
testing/web-platform/meta/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeText.html.ini
testing/web-platform/meta/2dcontext/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm.ini
toolkit/mozapps/extensions/content/default-theme-icon.svg
toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm
toolkit/mozapps/extensions/test/xpcshell/test_cache_certdb.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -177,19 +177,16 @@ pref("app.update.service.enabled", true)
 pref("extensions.update.enabled", true);
 pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
 pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
 pref("extensions.update.interval", 86400);  // Check for updates to Extensions and
                                             // Themes every day
 
 pref("extensions.webextensions.themes.icons.buttons", "back,forward,reload,stop,bookmark_star,bookmark_menu,downloads,home,app_menu,cut,copy,paste,new_window,new_private_window,save_page,print,history,full_screen,find,options,addons,developer,synced_tabs,open_file,sidebars,share_page,subscribe,text_encoding,email_link,forget,pocket");
 
-pref("lightweightThemes.update.enabled", true);
-pref("lightweightThemes.getMoreURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes");
-
 #if defined(MOZ_WIDEVINE_EME)
 pref("browser.eme.ui.enabled", true);
 #else
 pref("browser.eme.ui.enabled", false);
 #endif
 
 // UI tour experience.
 pref("browser.uitour.enabled", true);
@@ -1206,18 +1203,16 @@ pref("services.sync.prefs.sync.browser.u
 pref("services.sync.prefs.sync.dom.disable_open_during_load", true);
 pref("services.sync.prefs.sync.dom.disable_window_flip", true);
 pref("services.sync.prefs.sync.dom.disable_window_move_resize", true);
 pref("services.sync.prefs.sync.dom.event.contextmenu.enabled", true);
 pref("services.sync.prefs.sync.extensions.personas.current", true);
 pref("services.sync.prefs.sync.extensions.update.enabled", true);
 pref("services.sync.prefs.sync.intl.accept_languages", true);
 pref("services.sync.prefs.sync.layout.spellcheckDefault", true);
-pref("services.sync.prefs.sync.lightweightThemes.selectedThemeID", true);
-pref("services.sync.prefs.sync.lightweightThemes.usedThemes", true);
 pref("services.sync.prefs.sync.media.autoplay.default", true);
 pref("services.sync.prefs.sync.media.eme.enabled", true);
 pref("services.sync.prefs.sync.network.cookie.cookieBehavior", true);
 pref("services.sync.prefs.sync.network.cookie.lifetimePolicy", true);
 pref("services.sync.prefs.sync.network.cookie.thirdparty.sessionOnly", true);
 pref("services.sync.prefs.sync.permissions.default.image", true);
 pref("services.sync.prefs.sync.pref.advanced.images.disable_button.view_image", true);
 pref("services.sync.prefs.sync.pref.advanced.javascript.disable_button.advanced", true);
@@ -1256,24 +1251,16 @@ pref("services.sync.prefs.sync.spellchec
 pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
 
 // A preference that controls whether we should show the icon for a remote tab.
 // This pref has no UI but exists because some people may be concerned that
 // fetching these icons to show remote tabs may leak information about that
 // user's tabs and bookmarks. Note this pref is also synced.
 pref("services.sync.syncedTabs.showRemoteIcons", true);
 
-// Developer edition preferences
-#ifdef MOZ_DEV_EDITION
-pref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org",
-     sticky);
-#else
-pref("lightweightThemes.selectedThemeID", "default-theme@mozilla.org", sticky);
-#endif
-
 // Whether the character encoding menu is under the main Firefox button. This
 // preference is a string so that localizers can alter it.
 pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
 
 // Allow using tab-modal prompts when possible.
 pref("prompts.tab_modal.enabled", true);
 
 // Activates preloading of the new tab url.
--- a/browser/base/content/browser-compacttheme.js
+++ b/browser/base/content/browser-compacttheme.js
@@ -20,37 +20,36 @@ var CompactTheme = {
     }
     return this.styleSheet;
   },
 
   get isStyleSheetEnabled() {
     return this.styleSheet && !this.styleSheet.disabled;
   },
 
+  isCompactTheme(theme) {
+    return theme && (theme.id == "firefox-compact-dark@mozilla.org" ||
+                     theme.id == "firefox-compact-light@mozilla.org");
+  },
+
   get isThemeCurrentlyApplied() {
-    let theme = LightweightThemeManager.currentThemeWithPersistedData;
-    return theme && (
-           theme.id == "firefox-compact-dark@mozilla.org" ||
-           theme.id == "firefox-compact-light@mozilla.org");
+    return this.isCompactTheme(LightweightThemeManager.currentThemeWithFallback);
   },
 
   init() {
     Services.obs.addObserver(this, "lightweight-theme-styling-update");
 
     if (this.isThemeCurrentlyApplied) {
       this._toggleStyleSheet(true);
     }
   },
 
   observe(subject, topic, data) {
     if (topic == "lightweight-theme-styling-update") {
-      let { theme } = JSON.parse(data) || {};
-      if (theme && (
-          theme.id == "firefox-compact-light@mozilla.org" ||
-          theme.id == "firefox-compact-dark@mozilla.org")) {
+      if (this.isCompactTheme(subject.wrappedJSObject.theme)) {
         // We are using the theme ID on this object instead of always referencing
         // LightweightThemeManager.currentTheme in case this is a preview
         this._toggleStyleSheet(true);
       } else {
         this._toggleStyleSheet(false);
       }
     }
   },
--- a/browser/base/content/test/performance/browser_startup.js
+++ b/browser/base/content/test/performance/browser_startup.js
@@ -111,22 +111,16 @@ const startupPhases = {
     modules: new Set([
       "resource://gre/modules/AsyncPrefs.jsm",
       "resource://gre/modules/LoginManagerContextMenu.jsm",
       "resource://pdf.js/PdfStreamConverter.jsm",
     ]),
   }},
 };
 
-if (Services.prefs.getBoolPref("browser.startup.blankWindow") &&
-    Services.prefs.getCharPref("lightweightThemes.selectedThemeID") ==
-      "default-theme@mozilla.org") {
-  startupPhases["before profile selection"].whitelist.components.add("XULStore.js");
-}
-
 if (!gBrowser.selectedBrowser.isRemoteBrowser) {
   // With e10s disabled, Places and BrowserWindowTracker.jsm (from a
   // SessionSaver.jsm timer) intermittently get loaded earlier. Likely
   // due to messages from the 'content' process arriving synchronously
   // instead of crossing a process boundary.
   info("merging the 'before handling user events' blacklist into the " +
        "'before first paint' one when e10s is disabled.");
   let from = startupPhases["before handling user events"].blacklist;
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -304,29 +304,37 @@ function parseManifest(manifestUri) {
     }
   });
 }
 
 // If the given URI is a webextension manifest, extract the scripts
 // for any embedded APIs.  Returns the passed in URI if the manifest
 // is not a webextension manifest, null otherwise.
 async function parseJsonManifest(uri) {
+  uri = Services.io.newURI(convertToCodeURI(uri.spec));
+
   let raw = await fetchFile(uri.spec);
   let data;
   try {
     data = JSON.parse(raw);
   } catch (ex) {
     return uri;
   }
 
   // Simplistic test for whether this is a webextension manifest:
   if (data.manifest_version !== 2) {
     return uri;
   }
 
+  if (data.icons) {
+    for (let icon of Object.values(data.icons)) {
+      gReferencesFromCode.set(uri.resolve(icon), null);
+    }
+  }
+
   if (data.experiment_apis) {
     for (let api of Object.values(data.experiment_apis)) {
       if (api.parent && api.parent.script) {
         let script = uri.resolve(api.parent.script);
         gReferencesFromCode.set(script, null);
       }
     }
   }
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -70,18 +70,16 @@ browser.jar:
         content/browser/defaultthemes/3.icon.png      (content/defaultthemes/3.icon.png)
         content/browser/defaultthemes/3.preview.png   (content/defaultthemes/3.preview.png)
         content/browser/defaultthemes/4.header.png    (content/defaultthemes/4.header.png)
         content/browser/defaultthemes/4.icon.png      (content/defaultthemes/4.icon.png)
         content/browser/defaultthemes/4.preview.png   (content/defaultthemes/4.preview.png)
         content/browser/defaultthemes/5.header.png    (content/defaultthemes/5.header.png)
         content/browser/defaultthemes/5.icon.jpg      (content/defaultthemes/5.icon.jpg)
         content/browser/defaultthemes/5.preview.jpg   (content/defaultthemes/5.preview.jpg)
-        content/browser/defaultthemes/dark.icon.svg   (content/defaultthemes/dark.icon.svg)
-        content/browser/defaultthemes/light.icon.svg  (content/defaultthemes/light.icon.svg)
         content/browser/history-swipe-arrow.svg       (content/history-swipe-arrow.svg)
 *       content/browser/pageinfo/pageInfo.xul         (content/pageinfo/pageInfo.xul)
         content/browser/pageinfo/pageInfo.js          (content/pageinfo/pageInfo.js)
         content/browser/pageinfo/pageInfo.css         (content/pageinfo/pageInfo.css)
         content/browser/pageinfo/permissions.js       (content/pageinfo/permissions.js)
         content/browser/pageinfo/security.js          (content/pageinfo/security.js)
         content/browser/content-refreshblocker.js     (content/content-refreshblocker.js)
         content/browser/robot.ico                     (content/robot.ico)
@@ -123,8 +121,9 @@ browser.jar:
         content/browser/newInstallPage.js             (content/newInstallPage.js)
 
 % override chrome://global/content/netError.xhtml chrome://browser/content/aboutNetError.xhtml
 
 # L10n resources and overrides.
 % override chrome://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties
 % override chrome://global/locale/netError.dtd chrome://browser/locale/netError.dtd
 % override chrome://mozapps/locale/downloads/settingsChange.dtd chrome://browser/locale/downloads/settingsChange.dtd
+% override chrome://global/locale/app-extension-fields.properties chrome://browser/locale/app-extension-fields.properties
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -394,17 +394,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
   Discovery: "resource:///modules/Discovery.jsm",
   ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
   FileSource: "resource://gre/modules/L10nRegistry.jsm",
   FxAccounts: "resource://gre/modules/FxAccounts.jsm",
   HomePage: "resource:///modules/HomePage.jsm",
   HybridContentTelemetry: "resource://gre/modules/HybridContentTelemetry.jsm",
   Integration: "resource://gre/modules/Integration.jsm",
   L10nRegistry: "resource://gre/modules/L10nRegistry.jsm",
-  LightweightThemeManager: "resource://gre/modules/LightweightThemeManager.jsm",
   LiveBookmarkMigrator: "resource:///modules/LiveBookmarkMigrator.jsm",
   NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
   Normandy: "resource://normandy/Normandy.jsm",
   ObjectUtils: "resource://gre/modules/ObjectUtils.jsm",
   OS: "resource://gre/modules/osfile.jsm",
   PageActions: "resource:///modules/PageActions.jsm",
   PageThumbs: "resource://gre/modules/PageThumbs.jsm",
   PdfJs: "resource://pdf.js/PdfJs.jsm",
@@ -1032,63 +1031,22 @@ BrowserGlue.prototype = {
 
     // handle any UI migration
     this._migrateUI();
 
     listeners.init();
 
     SessionStore.init();
 
-    let vendorShortName = gBrandBundle.GetStringFromName("vendorShortName");
-
-    LightweightThemeManager.addBuiltInTheme({
-      id: "firefox-compact-light@mozilla.org",
-      name: gBrowserBundle.GetStringFromName("lightTheme.name"),
-      description: gBrowserBundle.GetStringFromName("lightTheme.description"),
-      iconURL: "resource:///chrome/browser/content/browser/defaultthemes/light.icon.svg",
-      textcolor: "rgb(24, 25, 26)",
-      icon_color: "rgb(24, 25, 26, 0.7)",
-      accentcolor: "#E3E4E6",
-      popup: "#fff",
-      popup_text: "#0c0c0d",
-      popup_border: "#ccc",
-      tab_line: "#0a84ff",
-      toolbarColor: "#f5f6f7",
-      toolbar_bottom_separator: "#ccc",
-      toolbar_field: "#fff",
-      toolbar_field_border: "#ccc",
-      author: vendorShortName,
-    });
-    LightweightThemeManager.addBuiltInTheme({
-      id: "firefox-compact-dark@mozilla.org",
-      name: gBrowserBundle.GetStringFromName("darkTheme.name"),
-      description: gBrowserBundle.GetStringFromName("darkTheme.description"),
-      iconURL: "resource:///chrome/browser/content/browser/defaultthemes/dark.icon.svg",
-      textcolor: "rgb(249, 249, 250)",
-      icon_color: "rgb(249, 249, 250, 0.7)",
-      accentcolor: "hsl(240, 5%, 5%)",
-      popup: "#4a4a4f",
-      popup_text: "rgb(249, 249, 250)",
-      popup_border: "#27272b",
-      tab_line: "#0a84ff",
-      toolbarColor: "hsl(240, 1%, 20%)",
-      toolbar_bottom_separator: "hsl(240, 5%, 5%)",
-      toolbar_field: "rgb(71, 71, 73)",
-      toolbar_field_border: "rgba(249, 249, 250, 0.2)",
-      toolbar_field_separator: "#5F6670",
-      toolbar_field_text: "rgb(249, 249, 250)",
-      ntp_background: "#2A2A2E",
-      ntp_text: "rgb(249, 249, 250)",
-      sidebar: "#38383D",
-      sidebar_text: "rgb(249, 249, 250)",
-      sidebar_border: "rgba(255, 255, 255, 0.1)",
-      author: vendorShortName,
-    }, {
-      useInDarkMode: true,
-    });
+    AddonManager.maybeInstallBuiltinAddon(
+        "firefox-compact-light@mozilla.org", "1.0",
+        "resource:///modules/themes/light/");
+    AddonManager.maybeInstallBuiltinAddon(
+        "firefox-compact-dark@mozilla.org", "1.0",
+        "resource:///modules/themes/dark/");
 
     Normandy.init();
 
     SaveToPocket.init();
     Services.obs.notifyObservers(null, "browser-ui-startup-complete");
   },
 
   _checkForOldBuildUpdates() {
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -179,20 +179,23 @@ XPCOMUtils.defineLazyGetter(this, "log",
   };
   return new scope.ConsoleAPI(consoleOptions);
 });
 
 var CustomizableUIInternal = {
   initialize() {
     log.debug("Initializing");
 
-    Services.obs.addObserver(this, "xpi-database-loaded");
-    if (AddonManagerPrivate.isDBLoaded()) {
-      this.observe(null, "xpi-database-loaded");
-    }
+    AddonManagerPrivate.databaseReady.then(async () => {
+      AddonManager.addAddonListener(this);
+
+      let addons = await AddonManager.getAddonsByTypes(["theme"]);
+      gDefaultTheme = addons.find(addon => addon.id == kDefaultThemeID);
+      gSelectedTheme = addons.find(addon => addon.isActive) || gDefaultTheme;
+    });
 
     this.addListener(this);
     this._defineBuiltInWidgets();
     this.loadSavedState();
     this._updateForNewVersion();
     this._markObsoleteBuiltinButtonsSeen();
 
     this.registerArea(CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, {
@@ -251,26 +254,16 @@ var CustomizableUIInternal = {
         "personal-bookmarks",
       ],
       defaultCollapsed: true,
     }, true);
 
     SearchWidgetTracker.init();
   },
 
-  async observe(subject, topic, data) {
-    if (topic == "xpi-database-loaded") {
-      AddonManager.addAddonListener(this);
-
-      let addons = await AddonManager.getAddonsByTypes(["theme"]);
-      gDefaultTheme = addons.find(addon => addon.id == kDefaultThemeID);
-      gSelectedTheme = addons.find(addon => addon.isActive) || gDefaultTheme;
-    }
-  },
-
   onEnabled(addon) {
     if (addon.type == "theme") {
       gSelectedTheme = addon;
     }
   },
 
   get _builtinAreas() {
     return new Set([
--- a/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
+++ b/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
@@ -55,17 +55,17 @@ add_task(async function() {
      "There should only be three themes (default, light, dark) in the 'My Themes' section by default");
   is(header.nextElementSibling.theme.id, DEFAULT_THEME_ID,
      "The first theme should be the default theme");
   is(header.nextElementSibling.nextElementSibling.theme.id, LIGHT_THEME_ID,
      "The second theme should be the light theme");
   is(header.nextElementSibling.nextElementSibling.nextElementSibling.theme.id, DARK_THEME_ID,
      "The third theme should be the dark theme");
 
-  let themeChangedPromise = promiseObserverNotified("lightweight-theme-changed");
+  let themeChangedPromise = promiseObserverNotified("lightweight-theme-styling-update");
   header.nextElementSibling.nextElementSibling.doCommand(); // Select light theme
   info("Clicked on light theme");
   await themeChangedPromise;
 
   let button = document.getElementById("customization-reset-button");
   await TestUtils.waitForCondition(() => !button.disabled);
 
   // Check restore defaults button is enabled.
@@ -82,17 +82,17 @@ add_task(async function() {
   let activeThemes = popup.querySelectorAll("toolbarbutton.customization-lwtheme-menu-theme[active]");
   is(activeThemes.length, 1, "Exactly 1 theme should be selected");
   if (activeThemes.length > 0) {
     is(activeThemes[0].theme.id, LIGHT_THEME_ID, "Light theme should be selected");
   }
 
   let firstLWTheme = footer.previousElementSibling;
   let firstLWThemeId = firstLWTheme.theme.id;
-  themeChangedPromise = promiseObserverNotified("lightweight-theme-changed");
+  themeChangedPromise = promiseObserverNotified("lightweight-theme-styling-update");
   firstLWTheme.doCommand();
   info("Clicked on first theme");
   await themeChangedPromise;
 
   await new Promise(executeSoon);
 
   popupShownPromise = popupShown(popup);
   EventUtils.synthesizeMouseAtCenter(themesButton, {});
@@ -113,18 +113,16 @@ add_task(async function() {
     iterNode = iterNode.nextElementSibling;
   }
   is(themeCount, 3,
      "There should be four themes in the 'My Themes' section");
 
   let defaultTheme = header.nextElementSibling;
   defaultTheme.doCommand();
   await new Promise(SimpleTest.executeSoon);
-  is(Services.prefs.getCharPref("lightweightThemes.selectedThemeID"),
-     DEFAULT_THEME_ID, "Default theme should be selected");
 
   // ensure current theme isn't set to "Default"
   popupShownPromise = popupShown(popup);
   EventUtils.synthesizeMouseAtCenter(themesButton, {});
   info("Clicked on themes button a fourth time");
   await popupShownPromise;
 
   // check that "Restore Defaults" button resets theme
--- a/browser/components/customizableui/test/browser_970511_undo_restore_default.js
+++ b/browser/components/customizableui/test/browser_970511_undo_restore_default.js
@@ -21,17 +21,17 @@ add_task(async function() {
   let popupShownPromise = popupShown(popup);
   EventUtils.synthesizeMouseAtCenter(themesButton, {});
   info("Clicked on themes button");
   await popupShownPromise;
 
   let header = document.getElementById("customization-lwtheme-menu-header");
   let firstLWTheme = header.nextElementSibling.nextElementSibling;
   let firstLWThemeId = firstLWTheme.theme.id;
-  let themeChangedPromise = promiseObserverNotified("lightweight-theme-changed");
+  let themeChangedPromise = promiseObserverNotified("lightweight-theme-styling-update");
   firstLWTheme.doCommand();
   info("Clicked on first theme");
   await themeChangedPromise;
 
   let theme = await AddonManager.getAddonByID(firstLWThemeId);
   is(theme.isActive, true, "Theme changed to first option");
 
   await gCustomizeMode.reset();
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/app-extension-fields.properties
@@ -0,0 +1,12 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# LOCALIZATION NOTE (extension.firefox-compact-light@mozilla.org.name): This is displayed in about:addons -> Appearance
+extension.firefox-compact-light@mozilla.org.name=Light
+extension.firefox-compact-light@mozilla.org.description=A theme with a light color scheme.
+
+# LOCALIZATION NOTE (extension.firefox-compact-dark@mozilla.org.name): This is displayed in about:addons -> Appearance
+extension.firefox-compact-dark@mozilla.org.name=Dark
+extension.firefox-compact-dark@mozilla.org.description=A theme with a dark color scheme.
+
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -230,24 +230,16 @@ addonInstallErrorIncompatible=%3$S could
 
 # LOCALIZATION NOTE (addonInstallErrorBlocklisted): %S is add-on name
 addonInstallErrorBlocklisted=%S could not be installed because it has a high risk of causing stability or security problems.
 
 unsignedAddonsDisabled.message=One or more installed add-ons cannot be verified and have been disabled.
 unsignedAddonsDisabled.learnMore.label=Learn More
 unsignedAddonsDisabled.learnMore.accesskey=L
 
-# LOCALIZATION NOTE (lightTheme.name): This is displayed in about:addons -> Appearance
-lightTheme.name=Light
-lightTheme.description=A theme with a light color scheme.
-
-# LOCALIZATION NOTE (darkTheme.name): This is displayed in about:addons -> Appearance
-darkTheme.name=Dark
-darkTheme.description=A theme with a dark color scheme.
-
 # LOCALIZATION NOTE (lwthemeInstallRequest.message2): %S will be replaced with
 # the host name of the site.
 lwthemeInstallRequest.message2=This site (%S) attempted to install a theme.
 lwthemeInstallRequest.allowButton2=Allow
 lwthemeInstallRequest.allowButton.accesskey2=a
 
 # LOCALIZATION NOTE (popupWarning.message): Semicolon-separated list of plural forms.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -11,16 +11,17 @@
   browser                                          (%browser/**/*.ftl)
 
 @AB_CD@.jar:
 % locale browser @AB_CD@ %locale/browser/
 # bookmarks.html is produced by LOCALIZED_GENERATED_FILES.
     locale/browser/bookmarks.html                  (bookmarks.html)
 
     locale/browser/accounts.properties             (%chrome/browser/accounts.properties)
+    locale/browser/app-extension-fields.properties (%chrome/browser/app-extension-fields.properties)
     locale/browser/browser.dtd                     (%chrome/browser/browser.dtd)
     locale/browser/baseMenuOverlay.dtd             (%chrome/browser/baseMenuOverlay.dtd)
     locale/browser/browser.properties              (%chrome/browser/browser.properties)
     locale/browser/customizableui/customizableWidgets.properties (%chrome/browser/customizableui/customizableWidgets.properties)
     locale/browser/uiDensity.properties            (%chrome/browser/uiDensity.properties)
     locale/browser/pocket.properties               (%chrome/browser/pocket.properties)
     locale/browser/search.properties               (%chrome/browser/search.properties)
     locale/browser/siteData.properties             (%chrome/browser/siteData.properties)
rename from browser/base/content/defaultthemes/dark.icon.svg
rename to browser/themes/addons/dark/icon.svg
new file mode 100644
--- /dev/null
+++ b/browser/themes/addons/dark/manifest.json
@@ -0,0 +1,39 @@
+{
+  "manifest_version": 2,
+
+  "applications": {
+    "gecko": {
+      "id": "firefox-compact-dark@mozilla.org"
+    }
+  },
+
+  "name": "Dark",
+  "description": "A theme with a dark color scheme.",
+  "author": "Mozilla",
+  "version": "1.0",
+
+  "icons": {"32": "icon.svg"},
+
+  "theme": {
+    "colors": {
+      "tab_background_text": "rgb(249, 249, 250)",
+      "icons": "rgb(249, 249, 250, 0.7)",
+      "frame": "hsl(240, 5%, 5%)",
+      "popup": "#4a4a4f",
+      "popup_text": "rgb(249, 249, 250)",
+      "popup_border": "#27272b",
+      "tab_line": "#0a84ff",
+      "toolbar": "hsl(240, 1%, 20%)",
+      "toolbar_bottom_separator": "hsl(240, 5%, 5%)",
+      "toolbar_field": "rgb(71, 71, 73)",
+      "toolbar_field_border": "rgba(249, 249, 250, 0.2)",
+      "toolbar_field_separator": "#5F6670",
+      "toolbar_field_text": "rgb(249, 249, 250)",
+      "ntp_background": "#2A2A2E",
+      "ntp_text": "rgb(249, 249, 250)",
+      "sidebar": "#38383D",
+      "sidebar_text": "rgb(249, 249, 250)",
+      "sidebar_border": "rgba(255, 255, 255, 0.1)"
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/themes/addons/dark/moz.build
@@ -0,0 +1,10 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXTRA_JS_MODULES.themes['dark'] += [
+    'icon.svg',
+    'manifest.json',
+]
rename from browser/base/content/defaultthemes/light.icon.svg
rename to browser/themes/addons/light/icon.svg
new file mode 100644
--- /dev/null
+++ b/browser/themes/addons/light/manifest.json
@@ -0,0 +1,32 @@
+{
+  "manifest_version": 2,
+
+  "applications": {
+    "gecko": {
+      "id": "firefox-compact-light@mozilla.org"
+    }
+  },
+
+  "name": "Light",
+  "description": "A theme with a light color scheme.",
+  "author": "Mozilla",
+  "version": "1.0",
+
+  "icons": {"32": "icon.svg"},
+
+  "theme": {
+    "colors": {
+      "tab_background_text": "rgb(24, 25, 26)",
+      "icons": "rgb(24, 25, 26, 0.7)",
+      "frame": "#E3E4E6",
+      "popup": "#fff",
+      "popup_text": "#0c0c0d",
+      "popup_border": "#ccc",
+      "tab_line": "#0a84ff",
+      "toolbar": "#f5f6f7",
+      "toolbar_bottom_separator": "#ccc",
+      "toolbar_field": "#fff",
+      "toolbar_field_border": "#ccc"
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/themes/addons/light/moz.build
@@ -0,0 +1,10 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXTRA_JS_MODULES.themes['light'] += [
+    'icon.svg',
+    'manifest.json',
+]
--- a/browser/themes/moz.build
+++ b/browser/themes/moz.build
@@ -11,16 +11,21 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
 
 if toolkit == 'cocoa':
     DIRS += ['osx']
 elif toolkit == 'gtk3':
     DIRS += ['linux']
 else:
     DIRS += ['windows']
 
+DIRS += [
+    'addons/dark',
+    'addons/light',
+]
+
 with Files('osx/**'):
     SCHEDULES.exclusive = ['macosx']
 
 with Files('linux/**'):
     SCHEDULES.exclusive = ['linux']
 
 with Files('windows/**'):
     SCHEDULES.exclusive = ['windows']
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -153,17 +153,17 @@
 #customization-lwtheme-button > .box-inherit > .box-inherit > .button-icon {
   width: 16px;
   height: 16px;
   border-radius: 2px;
   background-size: contain;
 }
 
 #customization-lwtheme-button > .box-inherit > .box-inherit > .button-icon {
-  background-image: url("chrome://mozapps/content/extensions/default-theme-icon.svg");
+  background-image: url("resource://gre/modules/themes/default/icon.svg");
 }
 
 #customization-uidensity-button > .box-inherit > .box-inherit > .button-icon {
   background-image: url("chrome://browser/skin/customizableui/density-normal.svg");
 }
 
 #widget-overflow-fixed-list > toolbarpaletteitem[place="menu-panel"],
 toolbarpaletteitem[place="toolbar"] {
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/LightweightThemes.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/LightweightThemes.jsm
@@ -1,87 +1,40 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["LightweightThemes"];
 
-const {LightweightThemeManager} = ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm");
-const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const {setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
+const {AddonManager} = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 
 var LightweightThemes = {
   init(libDir) {
-    // convert -size 3000x200 canvas:#333 black_theme.png
-    let blackImage = libDir.clone();
-    blackImage.append("black_theme.png");
-    this._blackImageURL = Services.io.newFileURI(blackImage).spec;
-
-    // convert -size 3000x200 canvas:#eee white_theme.png
-    let whiteImage = libDir.clone();
-    whiteImage.append("white_theme.png");
-    this._whiteImageURL = Services.io.newFileURI(whiteImage).spec;
   },
 
   configurations: {
     noLWT: {
       selectors: [],
       async applyConfig() {
-        LightweightThemeManager.currentTheme = null;
-      },
-    },
-
-    darkLWT: {
-      selectors: [],
-      applyConfig() {
-        LightweightThemeManager.setLocalTheme({
-          id:          "black",
-          name:        "black",
-          headerURL:   LightweightThemes._blackImageURL,
-          textcolor:   "#eeeeee",
-          accentcolor: "#111111",
-        });
-
-        // Wait for LWT listener
-        return new Promise(resolve => {
-          setTimeout(() => {
-            resolve();
-          }, 500);
-        });
-      },
-    },
-
-    lightLWT: {
-      selectors: [],
-      applyConfig() {
-        LightweightThemeManager.setLocalTheme({
-          id:          "white",
-          name:        "white",
-          headerURL:   LightweightThemes._whiteImageURL,
-          textcolor:   "#111111",
-          accentcolor: "#eeeeee",
-        });
-        // Wait for LWT listener
-        return new Promise(resolve => {
-          setTimeout(() => {
-            resolve();
-          }, 500);
-        });
+        let addon = await AddonManager.getAddonByID("default-theme@mozilla.org");
+        await addon.enable();
       },
     },
 
     compactLight: {
       selectors: [],
-      applyConfig() {
-        LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme("firefox-compact-light@mozilla.org");
+      async applyConfig() {
+        let addon = await AddonManager.getAddonByID("firefox-compact-light@mozilla.org");
+        await addon.enable();
       },
     },
 
     compactDark: {
       selectors: [],
-      applyConfig() {
-        LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme("firefox-compact-dark@mozilla.org");
+      async applyConfig() {
+        let addon = await AddonManager.getAddonByID("firefox-compact-dark@mozilla.org");
+        await addon.enable();
       },
     },
   },
 };
deleted file mode 100644
index f298189952fa8139a911365d3da9392f092dd0d6..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 94882c56dd6243501ca9dd66a76116d64667059f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/moz.build
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/moz.build
@@ -31,29 +31,27 @@ FINAL_TARGET_FILES.resources.configurati
     'configurations/Tabs.jsm',
     'configurations/TabsInTitlebar.jsm',
     'configurations/Toolbars.jsm',
     'configurations/UIDensities.jsm',
     'configurations/WindowSize.jsm',
 ]
 
 FINAL_TARGET_FILES.resources.lib += [
-    'lib/black_theme.png',
     'lib/borderify.xpi',
     'lib/mozscreenshots-script.js',
     'lib/mozscreenshots-style.css',
     'lib/mozscreenshots.html',
     'lib/permissionPrompts.html',
     'lib/robot.png',
     'lib/robot_center.png',
     'lib/robot_cropped_diagonal.png',
     'lib/robot_diagonal.png',
     'lib/robot_uncropped.png',
     'lib/robot_upperleft.png',
-    'lib/white_theme.png',
 ]
 
 FINAL_TARGET_FILES.resources.lib.controlCenter += [
     'lib/controlCenter/mixed.html',
     'lib/controlCenter/mixed_active.html',
     'lib/controlCenter/mixed_passive.html',
     'lib/controlCenter/password.html',
     'lib/controlCenter/tracking.html',
--- a/dom/canvas/test/test_canvas.html
+++ b/dom/canvas/test/test_canvas.html
@@ -5874,17 +5874,17 @@ ctx.fillStyle = '#0f0';
 ctx.fillRect(0, 0, 100, 50);
 
 var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
 g.addColorStop(0, '#f00');
 g.addColorStop(1, '#f00');
 ctx.fillStyle = g;
 ctx.fillRect(0, 0, 100, 50);
 
-todo_isPixel(ctx, 40,20, 0,255,0,255, 2);
+isPixel(ctx, 40,20, 0,255,0,255, 2);
 
 }
 </script>
 
 <!-- [[[ test_2d.gradient.linear.nonfinite.html ]]] -->
 
 <p>Canvas test: 2d.gradient.linear.nonfinite</p>
 <!-- Testing: createLinearGradient() throws NOT_SUPPORTED_ERR if arguments are not finite -->
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -1935,21 +1935,17 @@ already_AddRefed<ID2D1Brush> DrawTargetD
         static_cast<GradientStopsD2D *>(pat->mStops.get());
 
     if (!stops) {
       gfxDebug() << "No stops specified for gradient pattern.";
       return CreateTransparentBlackBrush();
     }
 
     if (pat->mBegin == pat->mEnd) {
-      uint32_t stopCount = stops->mStopCollection->GetGradientStopCount();
-      vector<D2D1_GRADIENT_STOP> d2dStops(stopCount);
-      stops->mStopCollection->GetGradientStops(&d2dStops.front(), stopCount);
-      d2dStops.back().color.a *= aAlpha;
-      return GetSolidColorBrush(d2dStops.back().color);
+      return CreateTransparentBlackBrush();
     }
 
     mDC->CreateLinearGradientBrush(
         D2D1::LinearGradientBrushProperties(D2DPoint(pat->mBegin),
                                             D2DPoint(pat->mEnd)),
         D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
         stops->mStopCollection, getter_AddRefs(gradBrush));
 
@@ -1968,16 +1964,20 @@ already_AddRefed<ID2D1Brush> DrawTargetD
     GradientStopsD2D *stops =
         static_cast<GradientStopsD2D *>(pat->mStops.get());
 
     if (!stops) {
       gfxDebug() << "No stops specified for gradient pattern.";
       return CreateTransparentBlackBrush();
     }
 
+    if (pat->mCenter1 == pat->mCenter2 && pat->mRadius1 == pat->mRadius2) {
+      return CreateTransparentBlackBrush();
+    }
+
     // This will not be a complex radial gradient brush.
     mDC->CreateRadialGradientBrush(
         D2D1::RadialGradientBrushProperties(
             D2DPoint(pat->mCenter2), D2DPoint(pat->mCenter1 - pat->mCenter2),
             pat->mRadius2, pat->mRadius2),
         D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
         stops->mStopCollection, getter_AddRefs(gradBrush));
 
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -9,16 +9,18 @@
 #include "ScaledFontBase.h"
 #include "FilterNodeSoftware.h"
 #include "HelpersSkia.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Vector.h"
 
+#include "skia/include/core/SkFont.h"
+#include "skia/include/core/SkTextBlob.h"
 #include "skia/include/core/SkSurface.h"
 #include "skia/include/core/SkTypeface.h"
 #include "skia/include/effects/SkGradientShader.h"
 #include "skia/include/core/SkColorFilter.h"
 #include "skia/include/core/SkRegion.h"
 #include "skia/include/effects/SkBlurImageFilter.h"
 #include "Blur.h"
 #include "Logging.h"
@@ -427,18 +429,19 @@ static void SetPaintPattern(SkPaint& aPa
       aPaint.setColor(ColorToSkColor(color, aAlpha));
       break;
     }
     case PatternType::LINEAR_GRADIENT: {
       const LinearGradientPattern& pat =
           static_cast<const LinearGradientPattern&>(aPattern);
       GradientStopsSkia* stops =
           static_cast<GradientStopsSkia*>(pat.mStops.get());
-      if (!stops || stops->mCount < 2 || !pat.mBegin.IsFinite() ||
-          !pat.mEnd.IsFinite()) {
+      if (!stops || stops->mCount < 2 ||
+          !pat.mBegin.IsFinite() || !pat.mEnd.IsFinite() ||
+          pat.mBegin == pat.mEnd) {
         aPaint.setColor(SK_ColorTRANSPARENT);
       } else {
         SkShader::TileMode mode =
             ExtendModeToTileMode(stops->mExtendMode, Axis::BOTH);
         SkPoint points[2];
         points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x),
                                   SkFloatToScalar(pat.mBegin.y));
         points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x),
@@ -460,19 +463,20 @@ static void SetPaintPattern(SkPaint& aPa
       }
       break;
     }
     case PatternType::RADIAL_GRADIENT: {
       const RadialGradientPattern& pat =
           static_cast<const RadialGradientPattern&>(aPattern);
       GradientStopsSkia* stops =
           static_cast<GradientStopsSkia*>(pat.mStops.get());
-      if (!stops || stops->mCount < 2 || !pat.mCenter1.IsFinite() ||
-          !IsFinite(pat.mRadius1) || !pat.mCenter2.IsFinite() ||
-          !IsFinite(pat.mRadius2)) {
+      if (!stops || stops->mCount < 2 ||
+          !pat.mCenter1.IsFinite() || !IsFinite(pat.mRadius1) ||
+          !pat.mCenter2.IsFinite() || !IsFinite(pat.mRadius2) ||
+          (pat.mCenter1 == pat.mCenter2 && pat.mRadius1 == pat.mRadius2)) {
         aPaint.setColor(SK_ColorTRANSPARENT);
       } else {
         SkShader::TileMode mode =
             ExtendModeToTileMode(stops->mExtendMode, Axis::BOTH);
         SkPoint points[2];
         points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x),
                                   SkFloatToScalar(pat.mCenter1.y));
         points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x),
@@ -590,17 +594,18 @@ struct AutoPaintSetup {
     // clear the clip rect. The other operators would be harder
     // but could be worth it to skip pushing a group.
     if (needsGroup) {
       mPaint.setBlendMode(SkBlendMode::kSrcOver);
       SkPaint temp;
       temp.setBlendMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
       temp.setAlpha(ColorFloatToByte(aOptions.mAlpha));
       // TODO: Get a rect here
-      mCanvas->saveLayerPreserveLCDTextRequests(nullptr, &temp);
+      SkCanvas::SaveLayerRec rec(nullptr, &temp, SkCanvas::kPreserveLCDText_SaveLayerFlag);
+      mCanvas->saveLayer(rec);
       mNeedsRestore = true;
     } else {
       mPaint.setAlpha(ColorFloatToByte(aOptions.mAlpha));
       mAlpha = aOptions.mAlpha;
     }
     mPaint.setFilterQuality(kLow_SkFilterQuality);
   }
 
@@ -1309,27 +1314,26 @@ void DrawTargetSkia::DrawGlyphs(ScaledFo
     return;
   }
 
   AntialiasMode aaMode = aFont->GetDefaultAAMode();
   if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
     aaMode = aOptions.mAntialiasMode;
   }
   bool aaEnabled = aaMode != AntialiasMode::NONE;
+  paint.mPaint.setAntiAlias(aaEnabled);
 
-  paint.mPaint.setAntiAlias(aaEnabled);
-  paint.mPaint.setTypeface(sk_ref_sp(typeface));
-  paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
-  paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+  SkFont font(sk_ref_sp(typeface), SkFloatToScalar(skiaFont->mSize));
 
-  bool shouldLCDRenderText = ShouldLCDRenderText(aFont->GetType(), aaMode);
-  paint.mPaint.setLCDRenderText(shouldLCDRenderText);
+  bool useSubpixelAA = ShouldLCDRenderText(aFont->GetType(), aaMode);
+  font.setEdging(useSubpixelAA ?
+                   SkFont::Edging::kSubpixelAntiAlias :
+                   (aaEnabled ? SkFont::Edging::kAntiAlias : SkFont::Edging::kAlias));
 
   bool useSubpixelText = true;
-
   switch (aFont->GetType()) {
     case FontType::FREETYPE:
     case FontType::FONTCONFIG:
       // SkFontHost_cairo does not support subpixel text positioning,
       // so only enable it for other font hosts.
       useSubpixelText = false;
       break;
     case FontType::MAC:
@@ -1344,52 +1348,45 @@ void DrawTargetSkia::DrawGlyphs(ScaledFo
         // support subpixel AA on transparent backgrounds, we still want font
         // smoothing for the thicker fonts, even if it is grayscale AA.
         //
         // With explicit Grayscale AA (from -moz-osx-font-smoothing:grayscale),
         // we want to have grayscale AA with no smoothing at all. This means
         // disabling the LCD font smoothing behaviour.
         // To accomplish this we have to explicitly disable hinting,
         // and disable LCDRenderText.
-        paint.mPaint.setHinting(SkPaint::kNo_Hinting);
+        font.setHinting(kNo_SkFontHinting);
       }
       break;
 #ifdef XP_WIN
     case FontType::DWRITE: {
       ScaledFontDWrite* dwriteFont = static_cast<ScaledFontDWrite*>(aFont);
-      paint.mPaint.setEmbeddedBitmapText(dwriteFont->UseEmbeddedBitmaps());
-
       if (dwriteFont->ForceGDIMode()) {
-        paint.mPaint.setEmbeddedBitmapText(true);
+        font.setEmbeddedBitmaps(true);
         useSubpixelText = false;
+      } else {
+        font.setEmbeddedBitmaps(dwriteFont->UseEmbeddedBitmaps());
       }
       break;
     }
 #endif
     default:
       break;
   }
 
-  paint.mPaint.setSubpixelText(useSubpixelText);
+  font.setSubpixel(useSubpixelText);
 
-  Vector<uint16_t, 64> indices;
-  Vector<SkPoint, 64> offsets;
-  if (!indices.resizeUninitialized(aBuffer.mNumGlyphs) ||
-      !offsets.resizeUninitialized(aBuffer.mNumGlyphs)) {
-    gfxDebug() << "Failed allocating Skia text buffers for GlyphBuffer";
-    return;
+  SkTextBlobBuilder builder;
+  auto runBuffer = builder.allocRunPos(font, aBuffer.mNumGlyphs);
+  for (uint32_t i = 0; i < aBuffer.mNumGlyphs; i++) {
+    runBuffer.glyphs[i] = aBuffer.mGlyphs[i].mIndex;
+    runBuffer.points()[i] = PointToSkPoint(aBuffer.mGlyphs[i].mPosition);
   }
-
-  for (uint32_t i = 0; i < aBuffer.mNumGlyphs; i++) {
-    indices[i] = aBuffer.mGlyphs[i].mIndex;
-    offsets[i] = PointToSkPoint(aBuffer.mGlyphs[i].mPosition);
-  }
-
-  mCanvas->drawPosText(indices.begin(), indices.length() * sizeof(uint16_t),
-                       offsets.begin(), paint.mPaint);
+  sk_sp<SkTextBlob> text = builder.make();
+  mCanvas->drawTextBlob(text, 0, 0, paint.mPaint);
 }
 
 void DrawTargetSkia::FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
                                 const Pattern& aPattern,
                                 const DrawOptions& aOptions) {
   DrawGlyphs(aFont, aBuffer, aPattern, nullptr, aOptions);
 }
 
--- a/gfx/2d/HelpersSkia.h
+++ b/gfx/2d/HelpersSkia.h
@@ -275,28 +275,28 @@ static inline SkShader::TileMode ExtendM
     case ExtendMode::REPEAT_Y: {
       return aAxis == Axis::Y_AXIS ? SkShader::kRepeat_TileMode
                                    : SkShader::kClamp_TileMode;
     }
   }
   return SkShader::kClamp_TileMode;
 }
 
-static inline SkPaint::Hinting GfxHintingToSkiaHinting(FontHinting aHinting) {
+static inline SkFontHinting GfxHintingToSkiaHinting(FontHinting aHinting) {
   switch (aHinting) {
     case FontHinting::NONE:
-      return SkPaint::kNo_Hinting;
+      return kNo_SkFontHinting;
     case FontHinting::LIGHT:
-      return SkPaint::kSlight_Hinting;
+      return kSlight_SkFontHinting;
     case FontHinting::NORMAL:
-      return SkPaint::kNormal_Hinting;
+      return kNormal_SkFontHinting;
     case FontHinting::FULL:
-      return SkPaint::kFull_Hinting;
+      return kFull_SkFontHinting;
   }
-  return SkPaint::kNormal_Hinting;
+  return kNormal_SkFontHinting;
 }
 
 static inline FillRule GetFillRule(SkPath::FillType aFillType) {
   switch (aFillType) {
     case SkPath::kWinding_FillType:
       return FillRule::FILL_WINDING;
     case SkPath::kEvenOdd_FillType:
       return FillRule::FILL_EVEN_ODD;
--- a/gfx/2d/ScaledFontBase.cpp
+++ b/gfx/2d/ScaledFontBase.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ScaledFontBase.h"
 
 #include "gfxPrefs.h"
 
 #ifdef USE_SKIA
 #  include "PathSkia.h"
-#  include "skia/include/core/SkPaint.h"
+#  include "skia/include/core/SkFont.h"
 #endif
 
 #ifdef USE_CAIRO
 #  include "PathCairo.h"
 #  include "DrawTargetCairo.h"
 #  include "HelpersCairo.h"
 #endif
 
@@ -104,36 +104,42 @@ bool ScaledFontBase::PopulateCairoScaled
 }
 #endif
 
 #ifdef USE_SKIA
 SkPath ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer) {
   SkTypeface *typeFace = GetSkTypeface();
   MOZ_ASSERT(typeFace);
 
-  SkPaint paint;
-  paint.setTypeface(sk_ref_sp(typeFace));
-  paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-  paint.setTextSize(SkFloatToScalar(mSize));
+  SkFont font(sk_ref_sp(typeFace), SkFloatToScalar(mSize));
 
   std::vector<uint16_t> indices;
-  std::vector<SkPoint> offsets;
   indices.resize(aBuffer.mNumGlyphs);
-  offsets.resize(aBuffer.mNumGlyphs);
-
   for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) {
     indices[i] = aBuffer.mGlyphs[i].mIndex;
-    offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x);
-    offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y);
   }
 
-  SkPath path;
-  paint.getPosTextPath(&indices.front(), aBuffer.mNumGlyphs * 2,
-                       &offsets.front(), &path);
-  return path;
+  struct Context {
+    const Glyph* mGlyph;
+    SkPath mPath;
+  } ctx = { aBuffer.mGlyphs };
+
+  font.getPaths(indices.data(), indices.size(),
+    [](const SkPath* glyphPath, const SkMatrix& scaleMatrix, void* ctxPtr) {
+      Context& ctx = *reinterpret_cast<Context*>(ctxPtr);
+      if (glyphPath) {
+        SkMatrix transMatrix(scaleMatrix);
+        transMatrix.postTranslate(SkFloatToScalar(ctx.mGlyph->mPosition.x),
+                                  SkFloatToScalar(ctx.mGlyph->mPosition.y));
+        ctx.mPath.addPath(*glyphPath, transMatrix);
+      }
+      ++ctx.mGlyph;
+    }, &ctx);
+
+  return ctx.mPath;
 }
 #endif
 
 already_AddRefed<Path> ScaledFontBase::GetPathForGlyphs(
     const GlyphBuffer &aBuffer, const DrawTarget *aTarget) {
 #ifdef USE_SKIA
   if (aTarget->GetBackendType() == BackendType::SKIA) {
     SkPath path = GetSkiaPathForGlyphs(aBuffer);
--- a/gfx/layers/composite/PaintCounter.cpp
+++ b/gfx/layers/composite/PaintCounter.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/gfx/Types.h"          // for Color, SurfaceFormat
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/Effects.h"  // for Effect, EffectChain, etc
 #include "mozilla/TimeStamp.h"       // for TimeStamp, TimeDuration
 #include "mozilla/Sprintf.h"
 
 #include "mozilla/gfx/HelpersSkia.h"
+#include "skia/include/core/SkFont.h"
 #include "PaintCounter.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 // Positioned below the chrome UI
@@ -43,22 +44,24 @@ PaintCounter::~PaintCounter() {
 
 void PaintCounter::Draw(Compositor* aCompositor, TimeDuration aPaintTime,
                         TimeDuration aCompositeTime) {
   char buffer[48];
   SprintfLiteral(buffer, "P: %.2f  C: %.2f", aPaintTime.ToMilliseconds(),
                  aCompositeTime.ToMilliseconds());
 
   SkPaint paint;
-  paint.setTextSize(32);
   paint.setColor(SkColorSetRGB(0, 255, 0));
   paint.setAntiAlias(true);
 
+  SkFont font(SkTypeface::MakeDefault(), 32);
+
   mCanvas->clear(SK_ColorTRANSPARENT);
-  mCanvas->drawText(buffer, strlen(buffer), 10, 30, paint);
+  mCanvas->drawSimpleText(buffer, strlen(buffer), kUTF8_SkTextEncoding,
+                          10, 30, font, paint);
   mCanvas->flush();
 
   if (!mTextureSource) {
     mTextureSource = aCompositor->CreateDataTextureSource();
     mTexturedEffect = CreateTexturedEffect(mFormat, mTextureSource,
                                            SamplingFilter::POINT, true);
     mTexturedEffect->mTextureCoords = Rect(0, 0, 1.0f, 1.0f);
   }
--- a/gfx/skia/generate_mozbuild.py
+++ b/gfx/skia/generate_mozbuild.py
@@ -71,19 +71,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
     UNIFIED_SOURCES += [
         'skia/src/fonts/SkFontMgr_indirect.cpp',
         'skia/src/fonts/SkRemotableFontMgr.cpp',
     ]
 
 # We should autogenerate these SSE related flags.
 
 if CONFIG['INTEL_ARCHITECTURE']:
-    SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
-    SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3']
-    SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
     SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
     SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
     SOURCES['skia/src/opts/SkOpts_sse42.cpp'].flags += ['-msse4.2']
     SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
     SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-mavx2', '-mf16c', '-mfma']
 elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += CONFIG['NEON_FLAGS']
 elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):
@@ -143,34 +140,44 @@ def generate_opt_sources():
           ('arm64', 'arm64', [':arm64', ':crc32']),
           ('none', 'none', [':none'])]
 
   opt_sources = {}
   for key, cpu, deps in cpus:
     subprocess.check_output('cd skia && bin/gn gen out/{0} --args=\'target_cpu="{1}"\''.format(key, cpu), shell=True)
     opt_sources[key] = set()
     for dep in deps:
-        output = subprocess.check_output('cd skia && bin/gn desc out/{0} {1} sources'.format(key, dep), shell=True)
-        if output:
-            opt_sources[key].update(parse_sources(output))
+        try:
+            output = subprocess.check_output('cd skia && bin/gn desc out/{0} {1} sources'.format(key, dep), shell=True)
+            if output:
+                opt_sources[key].update(parse_sources(output))
+        except subprocess.CalledProcessError as e:
+            if e.output.find('source_set') < 0:
+                raise
 
   return opt_sources
 
 def generate_platform_sources():
   sources = {}
   platform_args = {
     'win' : 'win_vc="C:/" win_sdk_version="00.0.00000.0"'
   }
   for plat in platforms:
     args = platform_args.get(plat, '')
     output = subprocess.check_output('cd skia && bin/gn gen out/{0} --args=\'target_os="{0}" {1}\' > /dev/null && bin/gn desc out/{0} :skia sources'.format(plat, args), shell=True)
     if output:
       sources[plat] = parse_sources(output)
 
-  deps = {':effects' : 'common', ':pdf' : 'pdf'}
+  plat_deps = {':fontmgr_win' : 'win', ':fontmgr_win_gdi' : 'win'}
+  for dep, key in plat_deps.items():
+    output = subprocess.check_output('cd skia && bin/gn desc out/{1} {0} sources'.format(dep, key), shell=True)
+    if output:
+      sources[key].update(parse_sources(output))
+
+  deps = {':pdf' : 'pdf'}
   for dep, key in deps.items():
     output = subprocess.check_output('cd skia && bin/gn desc out/linux {} sources'.format(dep), shell=True)
     if output:
       sources[key] = parse_sources(output)
 
   return dict(sources.items() + generate_opt_sources().items())
 
 
@@ -183,33 +190,33 @@ def generate_separated_sources(platform_
     'skia/src/fonts/',
     'skia/src/ports/SkImageEncoder',
     'skia/src/ports/SkImageGenerator',
     'SkBitmapRegion',
     'SkLite',
     'SkLight',
     'SkNormal',
     'codec',
+    'SkWGL',
     'SkMemory_malloc',
     'third_party',
     'Sk3D',
     'SkAnimCodecPlayer',
     'SkCamera',
     'SkCanvasStack',
     'SkCanvasStateUtils',
     'SkFrontBufferedStream',
     'SkInterpolator',
     'SkJSON',
     'SkMultiPictureDocument',
     'SkNullCanvas',
     'SkNWayCanvas',
     'SkOverdrawCanvas',
     'SkPaintFilterCanvas',
     'SkParseColor',
-    'SkTextBox',
     'SkWhitelistTypefaces',
     'SkXPS',
     'SkCreateCGImageRef',
     'skia/src/ports/SkGlobalInitialization',
   ]
 
   def isblacklisted(value):
     for item in blacklist:
@@ -220,17 +227,16 @@ def generate_separated_sources(platform_
 
   separated = defaultdict(set, {
     'common': {
       'skia/src/codec/SkMasks.cpp',
       'skia/src/effects/imagefilters/SkBlurImageFilter.cpp',
       'skia/src/effects/SkDashPathEffect.cpp',
       'skia/src/ports/SkDiscardableMemory_none.cpp',
       'skia/src/ports/SkGlobalInitialization_default.cpp',
-      'skia/src/ports/SkGlobalInitialization_default_imagefilters.cpp',
       'skia/src/ports/SkMemory_mozalloc.cpp',
       'skia/src/ports/SkImageGenerator_none.cpp',
       'skia/third_party/skcms/skcms.cc',
     },
     'android': {
       # 'skia/src/ports/SkDebug_android.cpp',
       'skia/src/ports/SkFontHost_cairo.cpp',
       # 'skia/src/ports/SkFontHost_FreeType.cpp',
@@ -293,58 +299,52 @@ def write_cflags(f, values, subsearch, c
     return
 
   for val in val_list:
     if iswhitelisted(val):
       write_indent(indent)
       f.write("SOURCES[\'" + val + "\'].flags += " + cflag + "\n")
 
 opt_whitelist = [
-  'skia/src/opts/Sk',
   'SkOpts',
   'SkBitmapProcState',
-  'SkBlitMask',
+  'SkBitmapScaler',
   'SkBlitRow',
   'SkBlitter',
-  'SkJumper',
   'SkSpriteBlitter',
   'SkMatrix.cpp',
   'skcms',
 ]
 
 # Unfortunately for now the gpu and pathops directories are
 # non-unifiable. Keep track of this and fix it.
 unified_blacklist = [
   'FontHost',
-  'SkAdvancedTypefaceMetrics',
   'SkBitmapProcState_matrixProcs.cpp',
   'SkBlitter_A8.cpp',
   'SkBlitter_ARGB32.cpp',
   'SkBlitter_RGB16.cpp',
   'SkBlitter_Sprite.cpp',
   'SkScan_Antihair.cpp',
   'SkScan_AntiPath.cpp',
   'SkScan_DAAPath.cpp',
   'SkParse.cpp',
   'SkPDFFont.cpp',
   'SkPictureData.cpp',
   'SkColorSpace',
-  'SkImage_Gpu.cpp',
   'SkPathOpsDebug.cpp',
   'SkParsePath.cpp',
   'SkRecorder.cpp',
   'SkMiniRecorder.cpp',
   'SkXfermode',
   'SkMatrix44.cpp',
   'SkRTree.cpp',
   'SkVertices.cpp',
-  'SkJumper',
   'SkSLHCodeGenerator.cpp',
   'SkSLLexer.cpp',
-  'SkSLLayoutLexer.cpp',
 ] + opt_whitelist
 
 def write_sources(f, values, indent):
   def isblacklisted(value):
     for item in unified_blacklist:
       if value.find(item) >= 0:
         return True
 
@@ -405,26 +405,29 @@ def write_mozbuild(sources):
 
   f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':\n")
   write_list(f, "SOURCES", sources['win'], 4)
 
   f.write("if CONFIG['INTEL_ARCHITECTURE']:\n")
   write_sources(f, sources['intel'], 4)
   write_cflags(f, sources['intel'], opt_whitelist, 'skia_opt_flags', 4)
 
-  f.write("elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):\n")
-  write_sources(f, sources['arm'], 4)
-  write_cflags(f, sources['arm'], opt_whitelist, 'skia_opt_flags', 4)
+  if sources['arm']:
+    f.write("elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):\n")
+    write_sources(f, sources['arm'], 4)
+    write_cflags(f, sources['arm'], opt_whitelist, 'skia_opt_flags', 4)
 
-  f.write("elif CONFIG['CPU_ARCH'] == 'aarch64':\n")
-  write_sources(f, sources['arm64'], 4)
-  write_cflags(f, sources['arm64'], opt_whitelist, 'skia_opt_flags', 4)
+  if sources['arm64']:
+    f.write("elif CONFIG['CPU_ARCH'] == 'aarch64':\n")
+    write_sources(f, sources['arm64'], 4)
+    write_cflags(f, sources['arm64'], opt_whitelist, 'skia_opt_flags', 4)
 
-  f.write("else:\n")
-  write_sources(f, sources['none'], 4)
+  if sources['none']:
+    f.write("else:\n")
+    write_sources(f, sources['none'], 4)
 
   f.write(footer)
 
   f.close()
 
   print 'Wrote ' + filename
 
 def main():
--- a/gfx/skia/moz.build
+++ b/gfx/skia/moz.build
@@ -33,66 +33,66 @@ UNIFIED_SOURCES += [
     'skia/src/core/SkAutoPixmapStorage.cpp',
     'skia/src/core/SkBBHFactory.cpp',
     'skia/src/core/SkBigPicture.cpp',
     'skia/src/core/SkBitmap.cpp',
     'skia/src/core/SkBitmapCache.cpp',
     'skia/src/core/SkBitmapController.cpp',
     'skia/src/core/SkBitmapDevice.cpp',
     'skia/src/core/SkBitmapProvider.cpp',
-    'skia/src/core/SkBitmapScaler.cpp',
     'skia/src/core/SkBlendMode.cpp',
     'skia/src/core/SkBlurMask.cpp',
     'skia/src/core/SkBlurMF.cpp',
     'skia/src/core/SkBuffer.cpp',
     'skia/src/core/SkCachedData.cpp',
     'skia/src/core/SkCanvas.cpp',
     'skia/src/core/SkCanvasPriv.cpp',
     'skia/src/core/SkClipStack.cpp',
     'skia/src/core/SkClipStackDevice.cpp',
     'skia/src/core/SkColor.cpp',
     'skia/src/core/SkColorFilter.cpp',
     'skia/src/core/SkColorMatrixFilterRowMajor255.cpp',
+    'skia/src/core/SkContourMeasure.cpp',
     'skia/src/core/SkConvertPixels.cpp',
     'skia/src/core/SkConvolver.cpp',
     'skia/src/core/SkCoverageDelta.cpp',
     'skia/src/core/SkCpu.cpp',
     'skia/src/core/SkCubicClipper.cpp',
     'skia/src/core/SkCubicMap.cpp',
     'skia/src/core/SkData.cpp',
     'skia/src/core/SkDataTable.cpp',
     'skia/src/core/SkDebug.cpp',
     'skia/src/core/SkDeferredDisplayList.cpp',
     'skia/src/core/SkDeferredDisplayListRecorder.cpp',
     'skia/src/core/SkDeque.cpp',
+    'skia/src/core/SkDescriptor.cpp',
     'skia/src/core/SkDevice.cpp',
     'skia/src/core/SkDistanceFieldGen.cpp',
     'skia/src/core/SkDocument.cpp',
     'skia/src/core/SkDraw.cpp',
     'skia/src/core/SkDraw_text.cpp',
     'skia/src/core/SkDraw_vertices.cpp',
     'skia/src/core/SkDrawable.cpp',
     'skia/src/core/SkDrawLooper.cpp',
     'skia/src/core/SkDrawShadowInfo.cpp',
     'skia/src/core/SkEdge.cpp',
     'skia/src/core/SkEdgeBuilder.cpp',
     'skia/src/core/SkEdgeClipper.cpp',
     'skia/src/core/SkExecutor.cpp',
-    'skia/src/core/SkFDot6Constants.cpp',
     'skia/src/core/SkFlattenable.cpp',
     'skia/src/core/SkFont.cpp',
     'skia/src/core/SkFontDescriptor.cpp',
     'skia/src/core/SkFontLCDConfig.cpp',
     'skia/src/core/SkFontMgr.cpp',
+    'skia/src/core/SkFontPriv.cpp',
     'skia/src/core/SkFontStream.cpp',
     'skia/src/core/SkGaussFilter.cpp',
     'skia/src/core/SkGeometry.cpp',
     'skia/src/core/SkGlobalInitialization_core.cpp',
     'skia/src/core/SkGlyph.cpp',
-    'skia/src/core/SkGlyphCache.cpp',
     'skia/src/core/SkGlyphRun.cpp',
     'skia/src/core/SkGlyphRunPainter.cpp',
     'skia/src/core/SkGpuBlurUtils.cpp',
     'skia/src/core/SkGraphics.cpp',
     'skia/src/core/SkHalf.cpp',
     'skia/src/core/SkICC.cpp',
     'skia/src/core/SkImageFilter.cpp',
     'skia/src/core/SkImageFilterCache.cpp',
@@ -105,38 +105,37 @@ UNIFIED_SOURCES += [
     'skia/src/core/SkMask.cpp',
     'skia/src/core/SkMaskBlurFilter.cpp',
     'skia/src/core/SkMaskCache.cpp',
     'skia/src/core/SkMaskFilter.cpp',
     'skia/src/core/SkMaskGamma.cpp',
     'skia/src/core/SkMath.cpp',
     'skia/src/core/SkMatrixImageFilter.cpp',
     'skia/src/core/SkMD5.cpp',
-    'skia/src/core/SkMetaData.cpp',
     'skia/src/core/SkMipMap.cpp',
     'skia/src/core/SkModeColorFilter.cpp',
     'skia/src/core/SkMultiPictureDraw.cpp',
     'skia/src/core/SkPaint.cpp',
-    'skia/src/core/SkPaint_text.cpp',
     'skia/src/core/SkPaintPriv.cpp',
     'skia/src/core/SkPath.cpp',
     'skia/src/core/SkPath_serial.cpp',
     'skia/src/core/SkPathEffect.cpp',
     'skia/src/core/SkPathMeasure.cpp',
     'skia/src/core/SkPathRef.cpp',
     'skia/src/core/SkPicture.cpp',
     'skia/src/core/SkPictureFlat.cpp',
     'skia/src/core/SkPictureImageGenerator.cpp',
     'skia/src/core/SkPicturePlayback.cpp',
     'skia/src/core/SkPictureRecord.cpp',
     'skia/src/core/SkPictureRecorder.cpp',
     'skia/src/core/SkPixelRef.cpp',
     'skia/src/core/SkPixmap.cpp',
     'skia/src/core/SkPoint.cpp',
     'skia/src/core/SkPoint3.cpp',
+    'skia/src/core/SkPromiseImageTexture.cpp',
     'skia/src/core/SkPtrRecorder.cpp',
     'skia/src/core/SkQuadClipper.cpp',
     'skia/src/core/SkRasterClip.cpp',
     'skia/src/core/SkRasterPipeline.cpp',
     'skia/src/core/SkRasterPipelineBlitter.cpp',
     'skia/src/core/SkReadBuffer.cpp',
     'skia/src/core/SkRecord.cpp',
     'skia/src/core/SkRecordDraw.cpp',
@@ -157,16 +156,17 @@ UNIFIED_SOURCES += [
     'skia/src/core/SkScan_Hairline.cpp',
     'skia/src/core/SkScan_Path.cpp',
     'skia/src/core/SkSemaphore.cpp',
     'skia/src/core/SkSharedMutex.cpp',
     'skia/src/core/SkSpecialImage.cpp',
     'skia/src/core/SkSpecialSurface.cpp',
     'skia/src/core/SkSpinlock.cpp',
     'skia/src/core/SkStream.cpp',
+    'skia/src/core/SkStrike.cpp',
     'skia/src/core/SkStrikeCache.cpp',
     'skia/src/core/SkString.cpp',
     'skia/src/core/SkStringUtils.cpp',
     'skia/src/core/SkStroke.cpp',
     'skia/src/core/SkStrokeRec.cpp',
     'skia/src/core/SkStrokerPriv.cpp',
     'skia/src/core/SkSurfaceCharacterization.cpp',
     'skia/src/core/SkSwizzle.cpp',
@@ -179,16 +179,17 @@ UNIFIED_SOURCES += [
     'skia/src/core/SkTypeface.cpp',
     'skia/src/core/SkTypeface_remote.cpp',
     'skia/src/core/SkTypefaceCache.cpp',
     'skia/src/core/SkUnPreMultiply.cpp',
     'skia/src/core/SkUtils.cpp',
     'skia/src/core/SkVertState.cpp',
     'skia/src/core/SkWriteBuffer.cpp',
     'skia/src/core/SkWriter32.cpp',
+    'skia/src/core/SkYUVASizeInfo.cpp',
     'skia/src/core/SkYUVPlanesCache.cpp',
     'skia/src/effects/imagefilters/SkBlurImageFilter.cpp',
     'skia/src/effects/SkDashPathEffect.cpp',
     'skia/src/image/SkImage.cpp',
     'skia/src/image/SkImage_Lazy.cpp',
     'skia/src/image/SkImage_Raster.cpp',
     'skia/src/image/SkSurface.cpp',
     'skia/src/image/SkSurface_Raster.cpp',
@@ -211,29 +212,27 @@ UNIFIED_SOURCES += [
     'skia/src/pathops/SkOpSpan.cpp',
     'skia/src/pathops/SkPathOpsAsWinding.cpp',
     'skia/src/pathops/SkPathOpsCommon.cpp',
     'skia/src/pathops/SkPathOpsConic.cpp',
     'skia/src/pathops/SkPathOpsCubic.cpp',
     'skia/src/pathops/SkPathOpsCurve.cpp',
     'skia/src/pathops/SkPathOpsLine.cpp',
     'skia/src/pathops/SkPathOpsOp.cpp',
-    'skia/src/pathops/SkPathOpsPoint.cpp',
     'skia/src/pathops/SkPathOpsQuad.cpp',
     'skia/src/pathops/SkPathOpsRect.cpp',
     'skia/src/pathops/SkPathOpsSimplify.cpp',
     'skia/src/pathops/SkPathOpsTightBounds.cpp',
     'skia/src/pathops/SkPathOpsTSect.cpp',
     'skia/src/pathops/SkPathOpsTypes.cpp',
     'skia/src/pathops/SkPathOpsWinding.cpp',
     'skia/src/pathops/SkPathWriter.cpp',
     'skia/src/pathops/SkReduceOrder.cpp',
     'skia/src/ports/SkDiscardableMemory_none.cpp',
     'skia/src/ports/SkGlobalInitialization_default.cpp',
-    'skia/src/ports/SkGlobalInitialization_default_imagefilters.cpp',
     'skia/src/ports/SkImageGenerator_none.cpp',
     'skia/src/ports/SkMemory_mozalloc.cpp',
     'skia/src/ports/SkOSFile_stdio.cpp',
     'skia/src/sfnt/SkOTTable_name.cpp',
     'skia/src/sfnt/SkOTUtils.cpp',
     'skia/src/shaders/gradients/Sk4fGradientBase.cpp',
     'skia/src/shaders/gradients/Sk4fLinearGradient.cpp',
     'skia/src/shaders/gradients/SkGradientShader.cpp',
@@ -251,35 +250,37 @@ UNIFIED_SOURCES += [
     'skia/src/shaders/SkPictureShader.cpp',
     'skia/src/shaders/SkShader.cpp',
     'skia/src/utils/mac/SkStream_mac.cpp',
     'skia/src/utils/SkBase64.cpp',
     'skia/src/utils/SkDashPath.cpp',
     'skia/src/utils/SkEventTracer.cpp',
     'skia/src/utils/SkFloatToDecimal.cpp',
     'skia/src/utils/SkMatrix22.cpp',
+    'skia/src/utils/SkMetaData.cpp',
     'skia/src/utils/SkOSPath.cpp',
     'skia/src/utils/SkPatchUtils.cpp',
     'skia/src/utils/SkPolyUtils.cpp',
     'skia/src/utils/SkShadowTessellator.cpp',
     'skia/src/utils/SkShadowUtils.cpp',
+    'skia/src/utils/SkTextUtils.cpp',
     'skia/src/utils/SkThreadUtils_pthread.cpp',
     'skia/src/utils/SkThreadUtils_win.cpp',
     'skia/src/utils/SkUTF.cpp',
     'skia/src/utils/win/SkAutoCoInitialize.cpp',
     'skia/src/utils/win/SkDWrite.cpp',
     'skia/src/utils/win/SkDWriteFontFileStream.cpp',
     'skia/src/utils/win/SkDWriteGeometrySink.cpp',
     'skia/src/utils/win/SkHRESULT.cpp',
     'skia/src/utils/win/SkIStream.cpp',
 ]
 SOURCES += [
     'skia/src/core/SkBitmapProcState.cpp',
     'skia/src/core/SkBitmapProcState_matrixProcs.cpp',
-    'skia/src/core/SkBlitMask_D32.cpp',
+    'skia/src/core/SkBitmapScaler.cpp',
     'skia/src/core/SkBlitRow_D32.cpp',
     'skia/src/core/SkBlitter.cpp',
     'skia/src/core/SkBlitter_A8.cpp',
     'skia/src/core/SkBlitter_ARGB32.cpp',
     'skia/src/core/SkBlitter_RGB565.cpp',
     'skia/src/core/SkBlitter_Sprite.cpp',
     'skia/src/core/SkColorSpace.cpp',
     'skia/src/core/SkColorSpaceXformCanvas.cpp',
@@ -295,56 +296,54 @@ SOURCES += [
     'skia/src/core/SkScan_Antihair.cpp',
     'skia/src/core/SkScan_AntiPath.cpp',
     'skia/src/core/SkScan_DAAPath.cpp',
     'skia/src/core/SkSpriteBlitter_ARGB32.cpp',
     'skia/src/core/SkSpriteBlitter_RGB565.cpp',
     'skia/src/core/SkVertices.cpp',
     'skia/src/core/SkXfermode.cpp',
     'skia/src/core/SkXfermodeInterpretation.cpp',
-    'skia/src/jumper/SkJumper.cpp',
     'skia/src/pathops/SkPathOpsDebug.cpp',
     'skia/src/utils/SkParse.cpp',
     'skia/src/utils/SkParsePath.cpp',
     'skia/third_party/skcms/skcms.cc',
 ]
 SOURCES['skia/src/core/SkBitmapProcState.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkBitmapProcState_matrixProcs.cpp'].flags += skia_opt_flags
-SOURCES['skia/src/core/SkBlitMask_D32.cpp'].flags += skia_opt_flags
+SOURCES['skia/src/core/SkBitmapScaler.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkBlitRow_D32.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkBlitter.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkBlitter_A8.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkBlitter_ARGB32.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkBlitter_RGB565.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkBlitter_Sprite.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkMatrix.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkOpts.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkSpriteBlitter_ARGB32.cpp'].flags += skia_opt_flags
 SOURCES['skia/src/core/SkSpriteBlitter_RGB565.cpp'].flags += skia_opt_flags
-SOURCES['skia/src/jumper/SkJumper.cpp'].flags += skia_opt_flags
 SOURCES['skia/third_party/skcms/skcms.cc'].flags += skia_opt_flags
 if CONFIG['MOZ_ENABLE_SKIA_PDF']:
     UNIFIED_SOURCES += [
         'skia/src/pdf/SkClusterator.cpp',
         'skia/src/pdf/SkDeflate.cpp',
         'skia/src/pdf/SkJpegInfo.cpp',
         'skia/src/pdf/SkKeyedImage.cpp',
         'skia/src/pdf/SkPDFBitmap.cpp',
-        'skia/src/pdf/SkPDFCanon.cpp',
         'skia/src/pdf/SkPDFConvertType1FontStream.cpp',
         'skia/src/pdf/SkPDFDevice.cpp',
         'skia/src/pdf/SkPDFDocument.cpp',
         'skia/src/pdf/SkPDFFormXObject.cpp',
         'skia/src/pdf/SkPDFGradientShader.cpp',
         'skia/src/pdf/SkPDFGraphicState.cpp',
         'skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.cpp',
         'skia/src/pdf/SkPDFMakeToUnicodeCmap.cpp',
         'skia/src/pdf/SkPDFMetadata.cpp',
         'skia/src/pdf/SkPDFResourceDict.cpp',
         'skia/src/pdf/SkPDFShader.cpp',
+        'skia/src/pdf/SkPDFSubsetFont.cpp',
         'skia/src/pdf/SkPDFTag.cpp',
         'skia/src/pdf/SkPDFTypes.cpp',
         'skia/src/pdf/SkPDFUtils.cpp',
     ]
     SOURCES += [
         'skia/src/pdf/SkPDFFont.cpp',
     ]
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
@@ -387,79 +386,33 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
         'skia/src/ports/SkFontMgr_win_dw_factory.cpp',
         'skia/src/ports/SkOSFile_win.cpp',
         'skia/src/ports/SkOSLibrary_win.cpp',
         'skia/src/ports/SkScalerContext_win_dw.cpp',
         'skia/src/ports/SkTLS_win.cpp',
         'skia/src/ports/SkTypeface_win_dw.cpp',
     ]
 if CONFIG['INTEL_ARCHITECTURE']:
-    UNIFIED_SOURCES += [
-        'skia/src/opts/opts_check_x86.cpp',
-    ]
     SOURCES += [
-        'skia/src/opts/SkBitmapProcState_opts_SSE2.cpp',
-        'skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp',
-        'skia/src/opts/SkBlitRow_opts_SSE2.cpp',
         'skia/src/opts/SkOpts_avx.cpp',
         'skia/src/opts/SkOpts_hsw.cpp',
         'skia/src/opts/SkOpts_sse41.cpp',
         'skia/src/opts/SkOpts_sse42.cpp',
         'skia/src/opts/SkOpts_ssse3.cpp',
     ]
-    SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += skia_opt_flags
     SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += skia_opt_flags
     SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += skia_opt_flags
     SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += skia_opt_flags
     SOURCES['skia/src/opts/SkOpts_sse42.cpp'].flags += skia_opt_flags
     SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += skia_opt_flags
-elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):
-    SOURCES += [
-        'skia/src/opts/SkBitmapProcState_arm_neon.cpp',
-        'skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp',
-        'skia/src/opts/SkBitmapProcState_opts_none.cpp',
-        'skia/src/opts/SkBlitMask_opts_arm.cpp',
-        'skia/src/opts/SkBlitMask_opts_arm_neon.cpp',
-        'skia/src/opts/SkBlitRow_opts_arm.cpp',
-        'skia/src/opts/SkBlitRow_opts_arm_neon.cpp',
-    ]
-    SOURCES['skia/src/opts/SkBitmapProcState_arm_neon.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBitmapProcState_opts_none.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitMask_opts_arm.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitMask_opts_arm_neon.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitRow_opts_arm.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitRow_opts_arm_neon.cpp'].flags += skia_opt_flags
 elif CONFIG['CPU_ARCH'] == 'aarch64':
     SOURCES += [
-        'skia/src/opts/SkBitmapProcState_arm_neon.cpp',
-        'skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp',
-        'skia/src/opts/SkBitmapProcState_opts_none.cpp',
-        'skia/src/opts/SkBlitMask_opts_arm.cpp',
-        'skia/src/opts/SkBlitMask_opts_arm_neon.cpp',
-        'skia/src/opts/SkBlitRow_opts_arm.cpp',
-        'skia/src/opts/SkBlitRow_opts_arm_neon.cpp',
         'skia/src/opts/SkOpts_crc32.cpp',
     ]
-    SOURCES['skia/src/opts/SkBitmapProcState_arm_neon.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBitmapProcState_opts_none.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitMask_opts_arm.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitMask_opts_arm_neon.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitRow_opts_arm.cpp'].flags += skia_opt_flags
-    SOURCES['skia/src/opts/SkBlitRow_opts_arm_neon.cpp'].flags += skia_opt_flags
     SOURCES['skia/src/opts/SkOpts_crc32.cpp'].flags += skia_opt_flags
-else:
-    SOURCES += [
-        'skia/src/opts/SkBitmapProcState_opts_none.cpp',
-        'skia/src/opts/SkBlitMask_opts_none.cpp',
-        'skia/src/opts/SkBlitRow_opts_none.cpp',
-    ]
 
 
 # We allow warnings for third-party code that can be updated from upstream.
 AllowCompilerWarnings()
 
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'skia/include/c',
@@ -495,19 +448,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
     UNIFIED_SOURCES += [
         'skia/src/fonts/SkFontMgr_indirect.cpp',
         'skia/src/fonts/SkRemotableFontMgr.cpp',
     ]
 
 # We should autogenerate these SSE related flags.
 
 if CONFIG['INTEL_ARCHITECTURE']:
-    SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
-    SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3']
-    SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
     SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
     SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
     SOURCES['skia/src/opts/SkOpts_sse42.cpp'].flags += ['-msse4.2']
     SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
     SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-mavx2', '-mf16c', '-mfma']
 elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += CONFIG['NEON_FLAGS']
 elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['CC_TYPE'] in ('clang', 'gcc'):
--- a/gfx/skia/skia/include/android/SkAndroidFrameworkUtils.h
+++ b/gfx/skia/skia/include/android/SkAndroidFrameworkUtils.h
@@ -4,20 +4,23 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkAndroidFrameworkUtils_DEFINED
 #define SkAndroidFrameworkUtils_DEFINED
 
 #include "SkTypes.h"
+#include "SkRefCnt.h"
 
-#ifdef SK_BUILD_FOR_ANDROID
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
 
 class SkCanvas;
+struct SkRect;
+class SkSurface;
 
 /**
  *  SkAndroidFrameworkUtils expose private APIs used only by Android framework.
  */
 class SkAndroidFrameworkUtils {
 public:
 
 #if SK_SUPPORT_GPU
@@ -26,13 +29,19 @@ public:
      *  set to 0x1. This function works only on a GPU canvas.
      *
      *  @param  canvas A GPU canvas that has a non-empty clip.
      *
      *  @return true on success or false if clip is empty or not a GPU canvas.
      */
     static bool clipWithStencil(SkCanvas* canvas);
 #endif //SK_SUPPORT_GPU
+
+    static void SafetyNetLog(const char*);
+
+    static sk_sp<SkSurface> getSurfaceFromCanvas(SkCanvas* canvas);
+
+    static int SaveBehind(SkCanvas* canvas, const SkRect* subset);
 };
 
-#endif // SK_BUILD_FOR_ANDROID
+#endif // SK_BUILD_FOR_ANDROID_ANDROID
 
 #endif // SkAndroidFrameworkUtils_DEFINED
--- a/gfx/skia/skia/include/android/SkAnimatedImage.h
+++ b/gfx/skia/skia/include/android/SkAnimatedImage.h
@@ -23,16 +23,29 @@ class SkPicture;
 class SK_API SkAnimatedImage : public SkDrawable {
 public:
     /**
      *  Create an SkAnimatedImage from the SkAndroidCodec.
      *
      *  Returns null on failure to allocate pixels. On success, this will
      *  decode the first frame.
      *
+     *  @param info Width and height may require scaling.
+     *  @param cropRect Rectangle to crop to after scaling.
+     *  @param postProcess Picture to apply after scaling and cropping.
+     */
+    static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>,
+            const SkImageInfo& info, SkIRect cropRect, sk_sp<SkPicture> postProcess);
+
+    /**
+     *  Create an SkAnimatedImage from the SkAndroidCodec.
+     *
+     *  Returns null on failure to allocate pixels. On success, this will
+     *  decode the first frame.
+     *
      *  @param scaledSize Size to draw the image, possibly requiring scaling.
      *  @param cropRect Rectangle to crop to after scaling.
      *  @param postProcess Picture to apply after scaling and cropping.
      */
     static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>,
             SkISize scaledSize, SkIRect cropRect, sk_sp<SkPicture> postProcess);
 
     /**
--- a/gfx/skia/skia/include/atlastext/SkAtlasTextFont.h
+++ b/gfx/skia/skia/include/atlastext/SkAtlasTextFont.h
@@ -3,32 +3,35 @@
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkAtlasTextFont_DEFINED
 #define SkAtlasTextFont_DEFINED
 
+#include "SkFont.h"
 #include "SkRefCnt.h"
 #include "SkTypeface.h"
 
 /** Represents a font at a size. TODO: What else do we need here (skewX, scaleX, vertical, ...)? */
 class SK_API SkAtlasTextFont : public SkRefCnt {
 public:
     static sk_sp<SkAtlasTextFont> Make(sk_sp<SkTypeface> typeface, SkScalar size) {
         return sk_sp<SkAtlasTextFont>(new SkAtlasTextFont(std::move(typeface), size));
     }
 
     SkTypeface* typeface() const { return fTypeface.get(); }
 
     sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
 
     SkScalar size() const { return fSize; }
 
+    SkFont makeFont() const { return SkFont(fTypeface, fSize); }
+
 private:
     SkAtlasTextFont(sk_sp<SkTypeface> typeface, SkScalar size)
             : fTypeface(std::move(typeface)), fSize(size) {}
 
     sk_sp<SkTypeface> fTypeface;
     SkScalar fSize;
 };
 
--- a/gfx/skia/skia/include/codec/SkCodec.h
+++ b/gfx/skia/skia/include/codec/SkCodec.h
@@ -15,17 +15,17 @@
 #include "SkColor.h"
 #include "SkEncodedImageFormat.h"
 #include "SkEncodedOrigin.h"
 #include "SkImageInfo.h"
 #include "SkPixmap.h"
 #include "SkSize.h"
 #include "SkStream.h"
 #include "SkTypes.h"
-#include "SkYUVSizeInfo.h"
+#include "SkYUVASizeInfo.h"
 
 #include <vector>
 
 class SkColorSpace;
 class SkData;
 class SkFrameHolder;
 class SkPngChunkReader;
 class SkSampler;
@@ -346,56 +346,71 @@ public:
         return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts);
     }
 
     /**
      *  If decoding to YUV is supported, this returns true.  Otherwise, this
      *  returns false and does not modify any of the parameters.
      *
      *  @param sizeInfo   Output parameter indicating the sizes and required
-     *                    allocation widths of the Y, U, and V planes.
+     *                    allocation widths of the Y, U, V, and A planes. Given current codec
+     *                    limitations the size of the A plane will always be 0 and the Y, U, V
+     *                    channels will always be planar.
      *  @param colorSpace Output parameter.  If non-NULL this is set to kJPEG,
      *                    otherwise this is ignored.
      */
-    bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
+    bool queryYUV8(SkYUVASizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
         if (nullptr == sizeInfo) {
             return false;
         }
 
-        return this->onQueryYUV8(sizeInfo, colorSpace);
+        bool result = this->onQueryYUV8(sizeInfo, colorSpace);
+        if (result) {
+            for (int i = 0; i <= 2; ++i) {
+                SkASSERT(sizeInfo->fSizes[i].fWidth > 0 && sizeInfo->fSizes[i].fHeight > 0 &&
+                         sizeInfo->fWidthBytes[i] > 0);
+            }
+            SkASSERT(!sizeInfo->fSizes[3].fWidth &&
+                     !sizeInfo->fSizes[3].fHeight &&
+                     !sizeInfo->fWidthBytes[3]);
+        }
+        return result;
     }
 
     /**
      *  Returns kSuccess, or another value explaining the type of failure.
      *  This always attempts to perform a full decode.  If the client only
      *  wants size, it should call queryYUV8().
      *
      *  @param sizeInfo   Needs to exactly match the values returned by the
      *                    query, except the WidthBytes may be larger than the
      *                    recommendation (but not smaller).
      *  @param planes     Memory for each of the Y, U, and V planes.
      */
-    Result getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
-        if (nullptr == planes || nullptr == planes[0] || nullptr == planes[1] ||
-                nullptr == planes[2]) {
+    Result getYUV8Planes(const SkYUVASizeInfo& sizeInfo, void* planes[SkYUVASizeInfo::kMaxCount]) {
+        if (!planes || !planes[0] || !planes[1] || !planes[2]) {
             return kInvalidInput;
         }
+        SkASSERT(!planes[3]); // TODO: is this a fair assumption?
 
         if (!this->rewindIfNeeded()) {
             return kCouldNotRewind;
         }
 
         return this->onGetYUV8Planes(sizeInfo, planes);
     }
 
     /**
      *  Prepare for an incremental decode with the specified options.
      *
      *  This may require a rewind.
      *
+     *  If kIncompleteInput is returned, may be called again after more data has
+     *  been provided to the source SkStream.
+     *
      *  @param dstInfo Info of the destination. If the dimensions do not match
      *      those of getInfo, this implies a scale.
      *  @param dst Memory to write to. Needs to be large enough to hold the subset,
      *      if present, or the full image as described in dstInfo.
      *  @param options Contains decoding options, including if memory is zero
      *      initialized and whether to decode a subset.
      *  @return Enum representing success or reason for failure.
      */
@@ -404,20 +419,21 @@ public:
 
     Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
         return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr);
     }
 
     /**
      *  Start/continue the incremental decode.
      *
-     *  Not valid to call before calling startIncrementalDecode().
+     *  Not valid to call before a call to startIncrementalDecode() returns
+     *  kSuccess.
      *
-     *  After the first call, should only be called again if more data has been
-     *  provided to the source SkStream.
+     *  If kIncompleteInput is returned, may be called again after more data has
+     *  been provided to the source SkStream.
      *
      *  Unlike getPixels and getScanlines, this does not do any filling. This is
      *  left up to the caller, since they may be skipping lines or continuing the
      *  decode later. In the latter case, they may choose to initialize all lines
      *  first, or only initialize the remaining lines after the first call.
      *
      *  @param rowsDecoded Optional output variable returning the total number of
      *      lines initialized. Only meaningful if this method returns kIncompleteInput.
@@ -703,21 +719,22 @@ protected:
      *                    will return kIncompleteInput and rowsDecoded will be set to
      *                    the number of scanlines that were successfully decoded.
      *                    This will allow getPixels() to fill the uninitialized memory.
      */
     virtual Result onGetPixels(const SkImageInfo& info,
                                void* pixels, size_t rowBytes, const Options&,
                                int* rowsDecoded) = 0;
 
-    virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const {
+    virtual bool onQueryYUV8(SkYUVASizeInfo*, SkYUVColorSpace*) const {
         return false;
     }
 
-    virtual Result onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) {
+    virtual Result onGetYUV8Planes(const SkYUVASizeInfo&,
+                                   void*[SkYUVASizeInfo::kMaxCount] /*planes*/) {
         return kUnimplemented;
     }
 
     virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
         // By default, subsets are not supported.
         return false;
     }
 
@@ -767,16 +784,24 @@ protected:
      *  This is unaffected by the SkScanlineOrder.
      *
      *  Returns -1 if we have not started a scanline decode.
      */
     int currScanline() const { return fCurrScanline; }
 
     virtual int onOutputScanline(int inputScanline) const;
 
+    /**
+     *  Return whether we can convert to dst.
+     *
+     *  Will be called for the appropriate frame, prior to initializing the colorXform.
+     */
+    virtual bool conversionSupported(const SkImageInfo& dst, bool srcIsOpaque,
+                                     bool needsColorXform);
+
     // Some classes never need a colorXform e.g.
     // - ICO uses its embedded codec's colorXform
     // - WBMP is just Black/White
     virtual bool usesColorXform() const { return true; }
     void applyColorXform(void* dst, const void* src, int count) const;
 
     bool colorXform() const { return fXformTime != kNo_XformTime; }
     bool xformOnDecode() const { return fXformTime == kDecodeRow_XformTime; }
@@ -813,24 +838,16 @@ private:
     skcms_ICCProfile                   fDstProfile;
     skcms_AlphaFormat                  fDstXformAlphaFormat;
 
     // Only meaningful during scanline decodes.
     int                                fCurrScanline;
 
     bool                               fStartedIncrementalDecode;
 
-    /**
-     *  Return whether we can convert to dst.
-     *
-     *  Will be called for the appropriate frame, prior to initializing the colorXform.
-     */
-    virtual bool conversionSupported(const SkImageInfo& dst, bool srcIsOpaque,
-                                     bool needsColorXform);
-
     bool initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha, bool srcIsOpaque);
 
     /**
      *  Return whether these dimensions are supported as a scale.
      *
      *  The codec may choose to cache the information about scale and subset.
      *  Either way, the same information will be passed to onGetPixels/onStart
      *  on success.
--- a/gfx/skia/skia/include/codec/SkCodecAnimation.h
+++ b/gfx/skia/skia/include/codec/SkCodecAnimation.h
@@ -34,10 +34,10 @@ namespace SkCodecAnimation {
         /**
          *  The next frame should be drawn on top of the previous frame - i.e.
          *  disregarding this one.
          *
          *  In a GIF, a value of 4 is also treated as RestorePrevious.
          */
         kRestorePrevious    = 3,
     };
-};
+}
 #endif // SkCodecAnimation_DEFINED
--- a/gfx/skia/skia/include/codec/SkEncodedOrigin.h
+++ b/gfx/skia/skia/include/codec/SkEncodedOrigin.h
@@ -2,22 +2,47 @@
  * Copyright 2017 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkEncodedOrigin_DEFINED
 #define SkEncodedOrigin_DEFINED
+
+#include "SkMatrix.h"
+
 // These values match the orientation www.exif.org/Exif2-2.PDF.
 enum SkEncodedOrigin {
     kTopLeft_SkEncodedOrigin     = 1, // Default
     kTopRight_SkEncodedOrigin    = 2, // Reflected across y-axis
     kBottomRight_SkEncodedOrigin = 3, // Rotated 180
     kBottomLeft_SkEncodedOrigin  = 4, // Reflected across x-axis
     kLeftTop_SkEncodedOrigin     = 5, // Reflected across x-axis, Rotated 90 CCW
     kRightTop_SkEncodedOrigin    = 6, // Rotated 90 CW
     kRightBottom_SkEncodedOrigin = 7, // Reflected across x-axis, Rotated 90 CW
     kLeftBottom_SkEncodedOrigin  = 8, // Rotated 90 CCW
     kDefault_SkEncodedOrigin     = kTopLeft_SkEncodedOrigin,
     kLast_SkEncodedOrigin        = kLeftBottom_SkEncodedOrigin,
 };
+
+/**
+ * Given an encoded origin and the width and height of the source data, returns a matrix
+ * that transforms the source rectangle [0, 0, w, h] to a correctly oriented destination
+ * rectangle, with the upper left corner still at [0, 0].
+ */
+static inline SkMatrix SkEncodedOriginToMatrix(SkEncodedOrigin origin, int w, int h) {
+    switch (origin) {
+        case     kTopLeft_SkEncodedOrigin: return SkMatrix::I();
+        case    kTopRight_SkEncodedOrigin: return SkMatrix::MakeAll(-1,  0, w,  0,  1, 0, 0, 0, 1);
+        case kBottomRight_SkEncodedOrigin: return SkMatrix::MakeAll(-1,  0, w,  0, -1, h, 0, 0, 1);
+        case  kBottomLeft_SkEncodedOrigin: return SkMatrix::MakeAll( 1,  0, 0,  0, -1, h, 0, 0, 1);
+        case     kLeftTop_SkEncodedOrigin: return SkMatrix::MakeAll( 0,  1, 0,  1,  0, 0, 0, 0, 1);
+        case    kRightTop_SkEncodedOrigin: return SkMatrix::MakeAll( 0, -1, h,  1,  0, 0, 0, 0, 1);
+        case kRightBottom_SkEncodedOrigin: return SkMatrix::MakeAll( 0, -1, h, -1,  0, w, 0, 0, 1);
+        case  kLeftBottom_SkEncodedOrigin: return SkMatrix::MakeAll( 0,  1, 0, -1,  0, w, 0, 0, 1);
+    }
+    SK_ABORT("Unexpected origin");
+    return SkMatrix::I();
+}
+
+
 #endif // SkEncodedOrigin_DEFINED
--- a/gfx/skia/skia/include/config/SkUserConfig.h
+++ b/gfx/skia/skia/include/config/SkUserConfig.h
@@ -130,30 +130,27 @@
 // On all platforms we have this byte order
 #define SK_A32_SHIFT 24
 #define SK_R32_SHIFT 16
 #define SK_G32_SHIFT 8
 #define SK_B32_SHIFT 0
 
 #define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
 
-// Don't use __stdcall with SkiaGLGlue - bug 1320644
-#define GR_GL_FUNCTION_TYPE
-
 #define SK_RASTERIZE_EVEN_ROUNDING
 
 #define SK_DISABLE_SLOW_DEBUG_VALIDATION 1
 
 #define SK_SUPPORT_DEPRECATED_CLIPOPS
 
+#define SK_SUPPORT_GPU 0
+
 #ifndef MOZ_IMPLICIT
 #  ifdef MOZ_CLANG_PLUGIN
 #    define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
 #  else
 #    define MOZ_IMPLICIT
 #  endif
 #endif
 
 #define MOZ_SKIA
 
-#define SK_SUPPORT_GPU 0
-
 #endif
--- a/gfx/skia/skia/include/core/SkBitmap.h
+++ b/gfx/skia/skia/include/core/SkBitmap.h
@@ -415,17 +415,17 @@ public:
 
         Calls reset() and returns false if:
         - rowBytes exceeds 31 bits
         - imageInfo.width() is negative
         - imageInfo.height() is negative
         - rowBytes is positive and less than imageInfo.width() times imageInfo.bytesPerPixel()
 
         @param imageInfo  contains width, height, SkAlphaType, SkColorType, SkColorSpace
-        @param rowBytes   imageInfo.minRowBytes or larger; or zero
+        @param rowBytes   imageInfo.minRowBytes() or larger; or zero
         @return           true if SkImageInfo set successfully
     */
     bool setInfo(const SkImageInfo& imageInfo, size_t rowBytes = 0);
 
     /** \enum SkBitmap::AllocFlags
         AllocFlags provides the option to zero pixel memory when allocated.
     */
     enum AllocFlags {
@@ -468,19 +468,17 @@ public:
         kZeroPixels_AllocFlag.
 
         flags set to kZeroPixels_AllocFlag offers equal or better performance than
         subsequently calling eraseColor() with SK_ColorTRANSPARENT.
 
         @param info   contains width, height, SkAlphaType, SkColorType, SkColorSpace
         @param flags  kZeroPixels_AllocFlag, or zero
     */
-    void allocPixelsFlags(const SkImageInfo& info, uint32_t flags) {
-        SkASSERT_RELEASE(this->tryAllocPixelsFlags(info, flags));
-    }
+    void allocPixelsFlags(const SkImageInfo& info, uint32_t flags);
 
     /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
         memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),
         or equal zero. Pass in zero for rowBytes to compute the minimum valid value.
 
         Returns false and calls reset() if SkImageInfo could not be set, or memory could
         not be allocated.
 
@@ -506,19 +504,17 @@ public:
         On most platforms, allocating pixel memory may succeed even though there is
         not sufficient memory to hold pixels; allocation does not take place
         until the pixels are written to. The actual behavior depends on the platform
         implementation of malloc().
 
         @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
         @param rowBytes  size of pixel row or larger; may be zero
     */
-    void allocPixels(const SkImageInfo& info, size_t rowBytes) {
-        SkASSERT_RELEASE(this->tryAllocPixels(info, rowBytes));
-    }
+    void allocPixels(const SkImageInfo& info, size_t rowBytes);
 
     /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
         memory.
 
         Returns false and calls reset() if SkImageInfo could not be set, or memory could
         not be allocated.
 
         On most platforms, allocating pixel memory may succeed even though there is
@@ -542,19 +538,17 @@ public:
 
         On most platforms, allocating pixel memory may succeed even though there is
         not sufficient memory to hold pixels; allocation does not take place
         until the pixels are written to. The actual behavior depends on the platform
         implementation of malloc().
 
         @param info  contains width, height, SkAlphaType, SkColorType, SkColorSpace
     */
-    void allocPixels(const SkImageInfo& info) {
-        this->allocPixels(info, info.minRowBytes());
-    }
+    void allocPixels(const SkImageInfo& info);
 
     /** Sets SkImageInfo to width, height, and native color type; and allocates
         pixel memory. If isOpaque is true, sets SkImageInfo to kOpaque_SkAlphaType;
         otherwise, sets to kPremul_SkAlphaType.
 
         Calls reset() and returns false if width exceeds 29 bits or is negative,
         or height is negative.
 
@@ -563,42 +557,34 @@ public:
         Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on
         the platform. SkBitmap drawn to output device skips converting its pixel format.
 
         @param width     pixel column count; must be zero or greater
         @param height    pixel row count; must be zero or greater
         @param isOpaque  true if pixels do not have transparency
         @return          true if pixel storage is allocated
     */
-    bool SK_WARN_UNUSED_RESULT tryAllocN32Pixels(int width, int height, bool isOpaque = false) {
-        SkImageInfo info = SkImageInfo::MakeN32(width, height,
-                                            isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
-        return this->tryAllocPixels(info);
-    }
+    bool SK_WARN_UNUSED_RESULT tryAllocN32Pixels(int width, int height, bool isOpaque = false);
 
     /** Sets SkImageInfo to width, height, and the native color type; and allocates
         pixel memory. If isOpaque is true, sets SkImageInfo to kPremul_SkAlphaType;
         otherwise, sets to kOpaque_SkAlphaType.
 
         Aborts if width exceeds 29 bits or is negative, or height is negative, or
         allocation fails. Abort steps may be provided by the user at compile time by
         defining SK_ABORT.
 
         Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on
         the platform. SkBitmap drawn to output device skips converting its pixel format.
 
         @param width     pixel column count; must be zero or greater
         @param height    pixel row count; must be zero or greater
         @param isOpaque  true if pixels do not have transparency
     */
-    void allocN32Pixels(int width, int height, bool isOpaque = false) {
-        SkImageInfo info = SkImageInfo::MakeN32(width, height,
-                                            isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
-        this->allocPixels(info);
-    }
+    void allocN32Pixels(int width, int height, bool isOpaque = false);
 
     /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef
         containing pixels and rowBytes. releaseProc, if not nullptr, is called
         immediately on failure or when pixels are no longer referenced. context may be
         nullptr.
 
         If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():
         calls releaseProc if present, calls reset(), and returns false.
@@ -638,65 +624,63 @@ public:
     bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
         return this->installPixels(info, pixels, rowBytes, nullptr, nullptr);
     }
 
     /** Sets SkImageInfo to pixmap.info() following the rules in setInfo(), and creates
         SkPixelRef containing pixmap.addr() and pixmap.rowBytes().
 
         If SkImageInfo could not be set, or pixmap.rowBytes() is less than
-        SkImageInfo::minRowBytes: calls reset(), and returns false.
+        SkImageInfo::minRowBytes(): calls reset(), and returns false.
 
         Otherwise, if pixmap.addr() equals nullptr: sets SkImageInfo, returns true.
 
         Caller must ensure that pixmap is valid for the lifetime of SkBitmap and SkPixelRef.
 
         @param pixmap  SkImageInfo, pixel address, and rowBytes()
         @return        true if SkImageInfo was set to pixmap.info()
     */
     bool installPixels(const SkPixmap& pixmap);
 
-    /** To be deprecated soon.
+    /** Deprecated.
     */
     bool installMaskPixels(const SkMask& mask);
 
     /** Replaces SkPixelRef with pixels, preserving SkImageInfo and rowBytes().
         Sets SkPixelRef origin to (0, 0).
 
-        If pixels is nullptr, or if info().colorType equals kUnknown_SkColorType;
+        If pixels is nullptr, or if info().colorType() equals kUnknown_SkColorType;
         release reference to SkPixelRef, and set SkPixelRef to nullptr.
 
         Caller is responsible for handling ownership pixel memory for the lifetime
         of SkBitmap and SkPixelRef.
 
         @param pixels  address of pixel storage, managed by caller
     */
     void setPixels(void* pixels);
 
     /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.
         The allocation size is determined by SkImageInfo width, height, and SkColorType.
 
-        Returns false if info().colorType is kUnknown_SkColorType, or allocation fails.
+        Returns false if info().colorType() is kUnknown_SkColorType, or allocation fails.
 
         @return  true if the allocation succeeds
     */
     bool SK_WARN_UNUSED_RESULT tryAllocPixels() {
         return this->tryAllocPixels((Allocator*)nullptr);
     }
 
     /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.
         The allocation size is determined by SkImageInfo width, height, and SkColorType.
 
-        Aborts if info().colorType is kUnknown_SkColorType, or allocation fails.
+        Aborts if info().colorType() is kUnknown_SkColorType, or allocation fails.
         Abort steps may be provided by the user at compile
         time by defining SK_ABORT.
     */
-    void allocPixels() {
-        this->allocPixels((Allocator*)nullptr);
-    }
+    void allocPixels();
 
     /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.
         The allocation size is determined by SkImageInfo width, height, and SkColorType.
         If allocator is nullptr, use HeapAllocator instead.
 
         Returns false if Allocator::allocPixelRef return false.
 
         @param allocator  instance of SkBitmap::Allocator instantiation
@@ -708,19 +692,17 @@ public:
         The allocation size is determined by SkImageInfo width, height, and SkColorType.
         If allocator is nullptr, use HeapAllocator instead.
 
         Aborts if Allocator::allocPixelRef return false. Abort steps may be provided by
         the user at compile time by defining SK_ABORT.
 
         @param allocator  instance of SkBitmap::Allocator instantiation
     */
-    void allocPixels(Allocator* allocator) {
-        SkASSERT_RELEASE(this->tryAllocPixels(allocator));
-    }
+    void allocPixels(Allocator* allocator);
 
     /** Returns SkPixelRef, which contains: pixel base address; its dimensions; and
         rowBytes(), the interval from one row to the next. Does not change SkPixelRef
         reference count. SkPixelRef may be shared by multiple bitmaps.
         If SkPixelRef has not been set, returns nullptr.
 
         @return  SkPixelRef, or nullptr
     */
@@ -773,43 +755,43 @@ public:
     uint32_t getGenerationID() const;
 
     /** Marks that pixels in SkPixelRef have changed. Subsequent calls to
         getGenerationID() return a different value.
     */
     void notifyPixelsChanged() const;
 
     /** Replaces pixel values with c. All pixels contained by bounds() are affected.
-        If the colorType() is kGray_8_SkColorType or k565_SkColorType, then alpha
+        If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then alpha
         is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,
         then RGB is ignored.
 
         @param c  unpremultiplied color
     */
     void eraseColor(SkColor c) const;
 
     /** Replaces pixel values with unpremultiplied color built from a, r, g, and b.
         All pixels contained by bounds() are affected.
-        If the colorType() is kGray_8_SkColorType or k565_SkColorType, then a
+        If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then a
         is ignored; r, g, and b are treated as opaque. If colorType() is kAlpha_8_SkColorType,
         then r, g, and b are ignored.
 
         @param a  amount of alpha, from fully transparent (0) to fully opaque (255)
         @param r  amount of red, from no red (0) to full red (255)
         @param g  amount of green, from no green (0) to full green (255)
         @param b  amount of blue, from no blue (0) to full blue (255)
     */
     void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
         this->eraseColor(SkColorSetARGB(a, r, g, b));
     }
 
     /** Replaces pixel values inside area with c. If area does not intersect bounds(),
         call has no effect.
 
-        If the colorType() is kGray_8_SkColorType or k565_SkColorType, then alpha
+        If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then alpha
         is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,
         then RGB is ignored.
 
         @param c     unpremultiplied color
         @param area  rectangle to fill
     */
     void erase(SkColor c, const SkIRect& area) const;
 
@@ -929,17 +911,17 @@ public:
     bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
 
     /** Copies a SkRect of pixels from SkBitmap to dstPixels. Copy starts at (srcX, srcY),
         and does not exceed SkBitmap (width(), height()).
 
         dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of
         destination. dstRowBytes specifics the gap from one destination row to the next.
         Returns true if pixels are copied. Returns false if:
-        - dstInfo.addr() equals nullptr
+        - dstInfo has no address
         - dstRowBytes is less than dstInfo.minRowBytes()
         - SkPixelRef is nullptr
 
         Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
         kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
         If SkBitmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
         If SkBitmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
         match. If SkBitmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
@@ -961,17 +943,17 @@ public:
 
     /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (srcX, srcY), and
         does not exceed SkBitmap (width(), height()).
 
         dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
         and row bytes of destination. dst.rowBytes() specifics the gap from one destination
         row to the next. Returns true if pixels are copied. Returns false if:
         - dst pixel storage equals nullptr
-        - dst.rowBytes is less than SkImageInfo::minRowBytes
+        - dst.rowBytes is less than SkImageInfo::minRowBytes()
         - SkPixelRef is nullptr
 
         Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
         kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
         If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
         If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
         match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
         false if pixel conversion is not possible.
@@ -989,17 +971,17 @@ public:
 
     /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (0, 0), and
         does not exceed SkBitmap (width(), height()).
 
         dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
         and row bytes of destination. dst.rowBytes() specifics the gap from one destination
         row to the next. Returns true if pixels are copied. Returns false if:
         - dst pixel storage equals nullptr
-        - dst.rowBytes is less than SkImageInfo::minRowBytes
+        - dst.rowBytes is less than SkImageInfo::minRowBytes()
         - SkPixelRef is nullptr
 
         Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
         kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
         If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
         If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
         match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
         false if pixel conversion is not possible.
@@ -1013,17 +995,17 @@ public:
 
     /** Copies a SkRect of pixels from src. Copy starts at (dstX, dstY), and does not exceed
         (src.width(), src.height()).
 
         src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
         and row bytes of source. src.rowBytes() specifics the gap from one source
         row to the next. Returns true if pixels are copied. Returns false if:
         - src pixel storage equals nullptr
-        - src.rowBytes is less than SkImageInfo::minRowBytes
+        - src.rowBytes is less than SkImageInfo::minRowBytes()
         - SkPixelRef is nullptr
 
         Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
         kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.
         If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.
         If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must
         match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns
         false if pixel conversion is not possible.
@@ -1041,55 +1023,33 @@ public:
 
     /** Copies a SkRect of pixels from src. Copy starts at (0, 0), and does not exceed
         (src.width(), src.height()).
 
         src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
         and row bytes of source. src.rowBytes() specifics the gap from one source
         row to the next. Returns true if pixels are copied. Returns false if:
         - src pixel storage equals nullptr
-        - src.rowBytes is less than SkImageInfo::minRowBytes
+        - src.rowBytes is less than SkImageInfo::minRowBytes()
         - SkPixelRef is nullptr
 
         Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
         kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.
         If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.
         If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must
         match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns
         false if pixel conversion is not possible.
 
         @param src  source SkPixmap: SkImageInfo, pixels, row bytes
         @return     true if src pixels are copied to SkBitmap
     */
     bool writePixels(const SkPixmap& src) {
         return this->writePixels(src, 0, 0);
     }
 
-#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
-    /** For use by Android framework only.
-
-        @return  true if setHasHardwareMipMap() has been called with true
-    */
-    bool hasHardwareMipMap() const {
-        return (fFlags & kHasHardwareMipMap_Flag) != 0;
-    }
-
-    /** For use by Android framework only.
-
-        @param hasHardwareMipMap  sets state
-    */
-    void setHasHardwareMipMap(bool hasHardwareMipMap) {
-        if (hasHardwareMipMap) {
-            fFlags |= kHasHardwareMipMap_Flag;
-        } else {
-            fFlags &= ~kHasHardwareMipMap_Flag;
-        }
-    }
-#endif
-
     /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
         or dst pixels cannot be allocated.
 
         Uses HeapAllocator to reserve memory for dst SkPixelRef.
 
         @param dst  holds SkPixelRef to fill with alpha layer
         @return     true if alpha layer was constructed in dst SkPixelRef
     */
@@ -1183,23 +1143,16 @@ public:
             @return        true if pixels are allocated
         */
         bool allocPixelRef(SkBitmap* bitmap) override;
     };
 
 private:
     enum Flags {
         kImageIsVolatile_Flag   = 0x02,
-#ifdef SK_BUILD_FOR_ANDROID
-        /* A hint for the renderer responsible for drawing this bitmap
-         * indicating that it should attempt to use mipmaps when this bitmap
-         * is drawn scaled down.
-         */
-        kHasHardwareMipMap_Flag = 0x08,
-#endif
     };
 
     sk_sp<SkPixelRef>   fPixelRef;
     SkPixmap            fPixmap;
     uint8_t             fFlags;
 
     friend class SkReadBuffer;        // unflatten
 };
--- a/gfx/skia/skia/include/core/SkBlendMode.h
+++ b/gfx/skia/skia/include/core/SkBlendMode.h
@@ -53,23 +53,23 @@ enum class SkBlendMode {
     kColor,                         //!< hue and saturation of source with luminosity of destination
     kLuminosity,                    //!< luminosity of source with hue and saturation of destination
     kLastMode          = kLuminosity, //!< last valid value
 };
 
 /** Returns name of blendMode as null-terminated C string.
 
     @param blendMode  one of:
-                      SkBlendMode::kClear, SkBlendMode::kSrc, SkBlendMode::kDst, SkBlendMode::kSrcOver,
-                      SkBlendMode::kDstOver, SkBlendMode::kSrcIn, SkBlendMode::kDstIn,
-                      SkBlendMode::kSrcOut, SkBlendMode::kDstOut, SkBlendMode::kSrcATop,
-                      SkBlendMode::kDstATop, SkBlendMode::kXor, SkBlendMode::kPlus,
-                      SkBlendMode::kModulate, SkBlendMode::kScreen, SkBlendMode::kOverlay,
-                      SkBlendMode::kDarken, SkBlendMode::kLighten, SkBlendMode::kColorDodge,
-                      SkBlendMode::kColorBurn, SkBlendMode::kHardLight, SkBlendMode::kSoftLight,
-                      SkBlendMode::kDifference, SkBlendMode::kExclusion, SkBlendMode::kMultiply,
-                      SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor,
-                      SkBlendMode::kLuminosity
+                      SkBlendMode::kClear, SkBlendMode::kSrc, SkBlendMode::kDst,
+                      SkBlendMode::kSrcOver, SkBlendMode::kDstOver, SkBlendMode::kSrcIn,
+                      SkBlendMode::kDstIn, SkBlendMode::kSrcOut, SkBlendMode::kDstOut,
+                      SkBlendMode::kSrcATop, SkBlendMode::kDstATop, SkBlendMode::kXor,
+                      SkBlendMode::kPlus, SkBlendMode::kModulate, SkBlendMode::kScreen,
+                      SkBlendMode::kOverlay, SkBlendMode::kDarken, SkBlendMode::kLighten,
+                      SkBlendMode::kColorDodge, SkBlendMode::kColorBurn, SkBlendMode::kHardLight,
+                      SkBlendMode::kSoftLight, SkBlendMode::kDifference, SkBlendMode::kExclusion,
+                      SkBlendMode::kMultiply, SkBlendMode::kHue, SkBlendMode::kSaturation,
+                      SkBlendMode::kColor, SkBlendMode::kLuminosity
     @return           C string
 */
 SK_API const char* SkBlendMode_Name(SkBlendMode blendMode);
 
 #endif
--- a/gfx/skia/skia/include/core/SkBlurTypes.h
+++ b/gfx/skia/skia/include/core/SkBlurTypes.h
@@ -5,17 +5,17 @@
  * found in the LICENSE file.
  */
 
 #ifndef SkBlurTypes_DEFINED
 #define SkBlurTypes_DEFINED
 
 #include "SkTypes.h"
 
-enum SkBlurStyle {
+enum SkBlurStyle : int {
     kNormal_SkBlurStyle,  //!< fuzzy inside and outside
     kSolid_SkBlurStyle,   //!< solid inside, fuzzy outside
     kOuter_SkBlurStyle,   //!< nothing inside, fuzzy outside
     kInner_SkBlurStyle,   //!< fuzzy inside, nothing outside
 
     kLastEnum_SkBlurStyle = kInner_SkBlurStyle,
 };
 
--- a/gfx/skia/skia/include/core/SkCanvas.h
+++ b/gfx/skia/skia/include/core/SkCanvas.h
@@ -17,34 +17,35 @@
 
 #ifndef SkCanvas_DEFINED
 #define SkCanvas_DEFINED
 
 #include "../private/SkMacros.h"
 #include "SkBlendMode.h"
 #include "SkClipOp.h"
 #include "SkDeque.h"
+#include "SkFontTypes.h"
 #include "SkPaint.h"
 #include "SkRasterHandleAllocator.h"
 #include "SkSurfaceProps.h"
 #include "SkVertices.h"
 
 class GrContext;
 class GrRenderTargetContext;
 class SkAndroidFrameworkUtils;
 class SkBaseDevice;
 class SkBitmap;
 class SkData;
 class SkDraw;
 class SkDrawable;
 struct SkDrawShadowRec;
+class SkFont;
 class SkGlyphRunBuilder;
 class SkImage;
 class SkImageFilter;
-class SkMetaData;
 class SkPath;
 class SkPicture;
 class SkPixmap;
 class SkRegion;
 class SkRRect;
 struct SkRSXform;
 class SkSurface;
 class SkSurface_Base;
@@ -60,17 +61,17 @@ class SkTextBlob;
     of all of clip values in the stack. The SkCanvas draw calls use SkPaint to supply drawing
     state such as color, SkTypeface, text size, stroke width, SkShader and so on.
 
     To draw to a pixel-based destination, create raster surface or GPU surface.
     Request SkCanvas from SkSurface to obtain the interface to draw.
     SkCanvas generated by raster surface draws to memory visible to the CPU.
     SkCanvas generated by GPU surface uses Vulkan or OpenGL to draw to the GPU.
 
-    To draw to a document, obtain SkCanvas from svg canvas, document pdf, or SkPictureRecorder.
+    To draw to a document, obtain SkCanvas from SVG canvas, document PDF, or SkPictureRecorder.
     SkDocument based SkCanvas and other SkCanvas subclasses reference SkBaseDevice describing the
     destination.
 
     SkCanvas can be constructed to draw to SkBitmap without first creating raster surface.
     This approach may be deprecated in the future.
 */
 class SK_API SkCanvas {
     enum PrivateSaveLayerFlags {
@@ -157,17 +158,17 @@ public:
         @param width   zero or greater
         @param height  zero or greater
         @param props   LCD striping orientation and setting for device independent fonts;
                        may be nullptr
         @return        SkCanvas placeholder with dimensions
     */
     SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr);
 
-    /** To be deprecated soon.
+    /** Private. For internal use only.
     */
     explicit SkCanvas(sk_sp<SkBaseDevice> device);
 
     /** Constructs a canvas that draws into bitmap.
         Sets SkSurfaceProps::kLegacyFontHost_InitType in constructed SkSurface.
 
         SkBitmap is copied so that subsequently editing bitmap will not affect
         constructed SkCanvas.
@@ -176,21 +177,23 @@ public:
 
         @param bitmap  width, height, SkColorType, SkAlphaType, and pixel
                        storage of raster surface
         @return        SkCanvas that can be used to draw into bitmap
     */
     explicit SkCanvas(const SkBitmap& bitmap);
 
 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+    /** Private.
+     */
     enum class ColorBehavior {
         kLegacy, //!< placeholder
     };
 
-    /** For use by Android framework only.
+    /** Private. For use by Android framework only.
 
         @param bitmap    specifies a bitmap for the canvas to draw into
         @param behavior  specializes this constructor; value is unused
         @return          SkCanvas that can be used to draw into bitmap
     */
     SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior);
 #endif
 
@@ -208,23 +211,16 @@ public:
     */
     SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
 
     /** Draws saved layers, if any.
         Frees up resources used by SkCanvas.
     */
     virtual ~SkCanvas();
 
-    /** Returns storage to associate additional data with the canvas.
-        The storage is freed when SkCanvas is deleted.
-
-        @return  storage that can be read from and written to
-    */
-    SkMetaData& getMetaData();
-
     /** Returns SkImageInfo for SkCanvas. If SkCanvas is not associated with raster surface or
         GPU surface, returned SkColorType is set to kUnknown_SkColorType.
 
         @return  dimensions and SkColorType of SkCanvas
     */
     SkImageInfo imageInfo() const;
 
     /** Copies SkSurfaceProps, if SkCanvas is associated with raster surface or
@@ -477,18 +473,18 @@ public:
         - Source and destination rectangles do not intersect.
         - bitmap does not have allocated pixels.
         - bitmap pixels could not be converted to SkCanvas imageInfo().colorType() or
         imageInfo().alphaType().
         - SkCanvas pixels are not writable; for instance, SkCanvas is document based.
         - bitmap pixels are inaccessible; for instance, bitmap wraps a texture.
 
         @param bitmap  contains pixels copied to SkCanvas
-        @param x       offset into SkCanvas writable pixels in x; may be negative
-        @param y       offset into SkCanvas writable pixels in y; may be negative
+        @param x       offset into SkCanvas writable pixels on x-axis; may be negative
+        @param y       offset into SkCanvas writable pixels on y-axis; may be negative
         @return        true if pixels were written to SkCanvas
     */
     bool writePixels(const SkBitmap& bitmap, int x, int y);
 
     /** Saves SkMatrix and clip.
         Calling restore() discards changes to SkMatrix and clip,
         restoring the SkMatrix and clip to their state when save() was called.
 
@@ -543,43 +539,16 @@ public:
         @param bounds  hint to limit the size of layer; may be nullptr
         @param paint   graphics state for layer; may be nullptr
         @return        depth of saved stack
     */
     int saveLayer(const SkRect& bounds, const SkPaint* paint) {
         return this->saveLayer(&bounds, paint);
     }
 
-    /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
-        LCD text is preserved when the layer is drawn to the prior layer.
-
-        Calling restore() discards changes to SkMatrix and clip, and draws layer.
-
-        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
-        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
-        clipPath(), clipRegion().
-
-        SkRect bounds suggests but does not define the layer size. To clip drawing to
-        a specific rectangle, use clipRect().
-
-        Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
-        SkBlendMode when restore() is called.
-
-        Call restoreToCount() with returned value to restore this and subsequent saves.
-
-        Draw text on an opaque background so that LCD text blends correctly with the
-        prior layer. LCD text drawn on a background with transparency may result in
-        incorrect blending.
-
-        @param bounds  hint to limit the size of layer; may be nullptr
-        @param paint   graphics state for layer; may be nullptr
-        @return        depth of saved stack
-    */
-    int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
-
     /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
 
         Calling restore() discards changes to SkMatrix and clip,
         and blends layer with alpha opacity onto prior layer.
 
         SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
         setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
         clipPath(), clipRegion().
@@ -598,24 +567,24 @@ public:
     int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
 
     /** \enum SkCanvas::SaveLayerFlagsSet
         SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
         defining how layer allocated by saveLayer() operates. It may be set to zero,
         kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags.
     */
     enum SaveLayerFlagsSet {
-        kPreserveLCDText_SaveLayerFlag  = 1 << 1, //!< creates layer for LCD text
+        kPreserveLCDText_SaveLayerFlag  = 1 << 1,
         kInitWithPrevious_SaveLayerFlag = 1 << 2, //!< initializes with previous contents
         kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag =
                                           1 << 3, //!< experimental: do not use
 
 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
         kDontClipToLayer_Legacy_SaveLayerFlag =
-           kDontClipToLayer_PrivateSaveLayerFlag, //!< to be deprecated soon
+           kDontClipToLayer_PrivateSaveLayerFlag, //!< deprecated
 #endif
     };
 
     typedef uint32_t SaveLayerFlags;
 
     /** \struct SkCanvas::SaveLayerRec
         SaveLayerRec contains the state used to create the layer.
     */
@@ -627,30 +596,33 @@ public:
         */
         SaveLayerRec() {}
 
         /** Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
 
             @param bounds          layer dimensions; may be nullptr
             @param paint           applied to layer when overlaying prior layer; may be nullptr
             @param saveLayerFlags  SaveLayerRec options to modify layer
-            @return                SaveLayerRec with empty backdrop
+            @return                SaveLayerRec with empty fBackdrop
         */
         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
             : fBounds(bounds)
             , fPaint(paint)
             , fSaveLayerFlags(saveLayerFlags)
         {}
 
         /** Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
 
             @param bounds          layer dimensions; may be nullptr
             @param paint           applied to layer when overlaying prior layer;
                                    may be nullptr
-            @param backdrop        prior layer copied with SkImageFilter; may be nullptr
+            @param backdrop        If not null, this causes the current layer to be filtered by
+                                   backdrop, and then drawn into the new layer
+                                   (respecting the current clip).
+                                   If null, the new layer is initialized with transparent-black.
             @param saveLayerFlags  SaveLayerRec options to modify layer
             @return                SaveLayerRec fully specified
         */
         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
                      SaveLayerFlags saveLayerFlags)
             : fBounds(bounds)
             , fPaint(paint)
             , fBackdrop(backdrop)
@@ -662,18 +634,20 @@ public:
             clipMatrix uses alpha channel of image, transformed by clipMatrix, to clip
             layer when drawn to SkCanvas.
 
             Implementation is not complete; has no effect if SkBaseDevice is GPU-backed.
 
             @param bounds          layer dimensions; may be nullptr
             @param paint           graphics state applied to layer when overlaying prior
                                    layer; may be nullptr
-            @param backdrop        prior layer copied with SkImageFilter;
-                                   may be nullptr
+            @param backdrop        If not null, this causes the current layer to be filtered by
+                                   backdrop, and then drawn into the new layer
+                                   (respecting the current clip).
+                                   If null, the new layer is initialized with transparent-black.
             @param clipMask        clip applied to layer; may be nullptr
             @param clipMatrix      matrix applied to clipMask; may be nullptr to use
                                    identity matrix
             @param saveLayerFlags  SaveLayerRec options to modify layer
             @return                SaveLayerRec fully specified
         */
         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
                      const SkImage* clipMask, const SkMatrix* clipMatrix,
@@ -687,17 +661,22 @@ public:
         {}
 
         /** hints at layer size limit */
         const SkRect*        fBounds         = nullptr;
 
         /** modifies overlay */
         const SkPaint*       fPaint          = nullptr;
 
-        /** applies SkImageFilter to prior layer */
+        /**
+         *  If not null, this triggers the same initialization behavior as setting
+         *  kInitWithPrevious_SaveLayerFlag on fSaveLayerFlags: the current layer is copied into
+         *  the new layer, rather than initializing the new layer with transparent-black.
+         *  This is then filtered by fBackdrop (respecting the current clip).
+         */
         const SkImageFilter* fBackdrop       = nullptr;
 
         /** clips layer with mask alpha */
         const SkImage*       fClipMask       = nullptr;
 
         /** transforms mask alpha used to clip */
         const SkMatrix*      fClipMatrix     = nullptr;
 
@@ -714,17 +693,17 @@ public:
         setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
         clipPath(), clipRegion().
 
         SaveLayerRec contains the state used to create the layer.
 
         Call restoreToCount() with returned value to restore this and subsequent saves.
 
         @param layerRec  layer state
-        @return          depth of save state stack
+        @return          depth of save state stack before this call was made.
     */
     int saveLayer(const SaveLayerRec& layerRec);
 
     /** Removes changes to SkMatrix and clip since SkCanvas state was
         last saved. The state is removed from the stack.
 
         Does nothing if the stack is empty.
     */
@@ -751,31 +730,31 @@ public:
     /** Translates SkMatrix by dx along the x-axis and dy along the y-axis.
 
         Mathematically, replaces SkMatrix with a translation matrix
         premultiplied with SkMatrix.
 
         This has the effect of moving the drawing by (dx, dy) before transforming
         the result with SkMatrix.
 
-        @param dx  distance to translate in x
-        @param dy  distance to translate in y
+        @param dx  distance to translate on x-axis
+        @param dy  distance to translate on y-axis
     */
     void translate(SkScalar dx, SkScalar dy);
 
     /** Scales SkMatrix by sx on the x-axis and sy on the y-axis.
 
         Mathematically, replaces SkMatrix with a scale matrix
         premultiplied with SkMatrix.
 
         This has the effect of scaling the drawing by (sx, sy) before transforming
         the result with SkMatrix.
 
-        @param sx  amount to scale in x
-        @param sy  amount to scale in y
+        @param sx  amount to scale on x-axis
+        @param sy  amount to scale on y-axis
     */
     void scale(SkScalar sx, SkScalar sy);
 
     /** Rotates SkMatrix by degrees. Positive degrees rotates clockwise.
 
         Mathematically, replaces SkMatrix with a rotation matrix
         premultiplied with SkMatrix.
 
@@ -1323,59 +1302,51 @@ public:
         @param path   SkPath to draw
         @param paint  stroke, blend, color, and so on, used to draw
     */
     void drawPath(const SkPath& path, const SkPaint& paint);
 
     /** Draws SkImage image, with its top-left corner at (left, top),
         using clip, SkMatrix, and optional SkPaint paint.
 
-        If paint is supplied, apply SkColorFilter, alpha, SkImageFilter, SkBlendMode,
-        and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
-        If paint contains SkMaskFilter, generate mask from image bounds. If generated
-        mask extends beyond image bounds, replicate image edge colors, just as SkShader
-        made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
-        image edge color when it samples outside of its bounds.
+        This is equivalent to drawImageRect() using a dst rect at (x,y) with the
+        same width and height of the image.
 
         @param image  uncompressed rectangular map of pixels
         @param left   left side of image
         @param top    top side of image
         @param paint  SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
                       and so on; or nullptr
     */
     void drawImage(const SkImage* image, SkScalar left, SkScalar top,
                    const SkPaint* paint = nullptr);
 
     /** Draws SkImage image, with its top-left corner at (left, top),
         using clip, SkMatrix, and optional SkPaint paint.
 
-        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
-        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
-        If paint contains SkMaskFilter, generate mask from image bounds. If generated
-        mask extends beyond image bounds, replicate image edge colors, just as SkShader
-        made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
-        image edge color when it samples outside of its bounds.
+        This is equivalent to drawImageRect() using a dst rect at (x,y) with the
+        same width and height of the image.
 
         @param image  uncompressed rectangular map of pixels
         @param left   left side of image
         @param top    pop side of image
         @param paint  SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
                       and so on; or nullptr
     */
     void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
                    const SkPaint* paint = nullptr) {
         this->drawImage(image.get(), left, top, paint);
     }
 
     /** \enum SkCanvas::SrcRectConstraint
         SrcRectConstraint controls the behavior at the edge of source SkRect,
         provided to drawImageRect(), trading off speed for precision.
 
-        SkImageFilter in SkPaint may sample multiple pixels in the image. Source SkRect
-        restricts the bounds of pixels that may be read. SkImageFilter may slow down if
+        SkFilterQuality in SkPaint may sample multiple pixels in the image. Source SkRect
+        restricts the bounds of pixels that may be read. SkFilterQuality may slow down if
         it cannot read outside the bounds, when sampling near the edge of source SkRect.
         SrcRectConstraint specifies whether an SkImageFilter is allowed to read pixels
         outside source SkRect.
     */
     enum SrcRectConstraint {
         kStrict_SrcRectConstraint, //!< sample only inside bounds; slower
         kFast_SrcRectConstraint,   //!< sample outside bounds; faster
     };
@@ -1386,16 +1357,20 @@ public:
         If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
         SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
         If paint contains SkMaskFilter, generate mask from image bounds.
 
         If generated mask extends beyond image bounds, replicate image edge colors, just
         as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
         replicates the image edge color when it samples outside of its bounds.
 
+        When using a shader or shader mask filter, its coordinate system is based on the
+        current CTM, so will reflect the dst rect geometry and is equivalent to
+        drawRect(dst). The src rect is only used to access the provided image.
+
         constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
         sample within src; set to kFast_SrcRectConstraint allows sampling outside to
         improve performance.
 
         @param image       SkImage containing pixels, dimensions, and format
         @param src         source SkRect of image to draw from
         @param dst         destination SkRect of image to draw to
         @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
@@ -1414,16 +1389,20 @@ public:
         If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
         SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
         If paint contains SkMaskFilter, generate mask from image bounds.
 
         If generated mask extends beyond image bounds, replicate image edge colors, just
         as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
         replicates the image edge color when it samples outside of its bounds.
 
+        When using a shader or shader mask filter, its coordinate system is based on the
+        current CTM, so will reflect the dst rect geometry and is equivalent to
+        drawRect(dst). The src rect is only used to access the provided image.
+
         constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
         sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
         improve performance.
 
         @param image       SkImage containing pixels, dimensions, and format
         @param isrc        source SkIRect of image to draw from
         @param dst         destination SkRect of image to draw to
         @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
@@ -1440,43 +1419,41 @@ public:
         If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
         SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
         If paint contains SkMaskFilter, generate mask from image bounds.
 
         If generated mask extends beyond image bounds, replicate image edge colors, just
         as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
         replicates the image edge color when it samples outside of its bounds.
 
-        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
-        sample within image; set to kFast_SrcRectConstraint allows sampling outside to
-        improve performance.
+        When using a shader or shader mask filter, its coordinate system is based on the
+        current CTM, so will reflect the dst rect geometry and is equivalent to
+        drawRect(dst).
 
         @param image       SkImage containing pixels, dimensions, and format
         @param dst         destination SkRect of image to draw to
         @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
                            and so on; or nullptr
-        @param constraint  filter strictly within image or draw faster
     */
-    void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
-                       SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+    void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint);
 
     /** Draws SkRect src of SkImage image, scaled and translated to fill SkRect dst.
         Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
 
         If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
         SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
         If paint contains SkMaskFilter, generate mask from image bounds.
 
         If generated mask extends beyond image bounds, replicate image edge colors, just
         as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
         replicates the image edge color when it samples outside of its bounds.
 
-        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
-        sample within src; set to kFast_SrcRectConstraint allows sampling outside to
-        improve performance.
+        When using a shader or shader mask filter, its coordinate system is based on the
+        current CTM, so will reflect the dst rect geometry and is equivalent to
+        drawRect(dst). The src rect is only used to access the provided image.
 
         @param image       SkImage containing pixels, dimensions, and format
         @param src         source SkRect of image to draw from
         @param dst         destination SkRect of image to draw to
         @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
                            and so on; or nullptr
         @param constraint  filter strictly within src or draw faster
     */
@@ -1493,16 +1470,20 @@ public:
         If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
         SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
         If paint contains SkMaskFilter, generate mask from image bounds.
 
         If generated mask extends beyond image bounds, replicate image edge colors, just
         as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
         replicates the image edge color when it samples outside of its bounds.
 
+        When using a shader or shader mask filter, its coordinate system is based on the
+        current CTM, so will reflect the dst rect geometry and is equivalent to
+        drawRect(dst). The src rect is only used to access the provided image.
+
         constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
         sample within image; set to kFast_SrcRectConstraint allows sampling outside to
         improve performance.
 
         @param image       SkImage containing pixels, dimensions, and format
         @param isrc        source SkIRect of image to draw from
         @param dst         destination SkRect of image to draw to
         @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
@@ -1521,29 +1502,31 @@ public:
         If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
         SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
         If paint contains SkMaskFilter, generate mask from image bounds.
 
         If generated mask extends beyond image bounds, replicate image edge colors, just
         as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
         replicates the image edge color when it samples outside of its bounds.
 
+        When using a shader or shader mask filter, its coordinate system is based on the
+        current CTM, so will reflect the dst rect geometry and is equivalent to
+        drawRect(dst).
+
         constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
         sample within image; set to kFast_SrcRectConstraint allows sampling outside to
         improve performance.
 
         @param image       SkImage containing pixels, dimensions, and format
         @param dst         destination SkRect of image to draw to
         @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
                            and so on; or nullptr
-        @param constraint  filter strictly within image or draw faster
     */
-    void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
-                       SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
-        this->drawImageRect(image.get(), dst, paint, constraint);
+    void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint) {
+        this->drawImageRect(image.get(), dst, paint);
     }
 
     /** Draws SkImage image stretched proportionally to fit into SkRect dst.
         SkIRect center divides the image into nine sections: four sides, four corners, and
         the center. Corners are unmodified or scaled down proportionately if their sides
         are larger than dst; center and four sides are scaled to fit remaining space, if any.
 
         Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
@@ -1815,171 +1798,160 @@ public:
         @param lattice  division of bitmap into fixed and variable rectangles
         @param dst      destination SkRect of image to draw to
         @param paint    SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
                         and so on; or nullptr
     */
     void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
                           const SkPaint* paint = nullptr);
 
-    /** Draws text, with origin at (x, y), using clip, SkMatrix, and SkPaint paint.
-
-        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as
-        UTF-8.
-
-        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default
-        text draws left to right, positioning the first glyph left side bearing at x
-        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.
+    /**
+     * Experimental. Controls anti-aliasing of each edge of images in an image-set.
+     */
+    enum QuadAAFlags : unsigned {
+        kLeft_QuadAAFlag    = 0b0001,
+        kTop_QuadAAFlag     = 0b0010,
+        kRight_QuadAAFlag   = 0b0100,
+        kBottom_QuadAAFlag  = 0b1000,
+
+        kNone_QuadAAFlags   = 0b0000,
+        kAll_QuadAAFlags    = 0b1111,
+    };
+
+    /** This is used by the experimental API below. */
+    struct ImageSetEntry {
+        sk_sp<const SkImage> fImage;
+        SkRect fSrcRect;
+        SkRect fDstRect;
+        float fAlpha;
+        unsigned fAAFlags;  // QuadAAFlags
+    };
+
+    /**
+     * This is an experimental API for the SkiaRenderer Chromium project. The signature will
+     * surely evolve if this is not removed. It currently offers no performance advantage over
+     * drawing images independently, though may in the future. The antialiasing flags are intended
+     * to allow control over each edge's AA status, to allow perfect seaming for tile sets. The
+     * current implementation only antialiases if all edges are flagged, however.
+     * Results are undefined if an image's src rect is not within the image's bounds.
+     */
+    void experimental_DrawImageSetV1(const ImageSetEntry imageSet[], int cnt,
+                                     SkFilterQuality quality, SkBlendMode mode);
+
+    /**
+     * This is an experimental API for the SkiaRenderer Chromium project. The signature will
+     * surely evolve if this is not removed. The antialiasing flags are intended to allow control
+     * over each edge's AA status, to allow perfect seaming for tile sets.
+     *
+     * When not fully supported, the implementation only antialiases if all edges are flagged.
+     */
+    void experimental_DrawEdgeAARectV1(const SkRect& r, QuadAAFlags edgeAA, SkColor color,
+                                       SkBlendMode mode);
+
+    /** Draws text, with origin at (x, y), using clip, SkMatrix, SkFont font,
+        and SkPaint paint.
+
+        When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
+        SkTextEncoding::kUTF32, this function uses the default
+        character-to-glyph mapping from the SkTypeface in font.  It does not
+        perform typeface fallback for characters not found in the SkTypeface.
+        It does not perform kerning or other complex shaping; glyphs are
+        positioned based on their default advances.
+
+        Text meaning depends on SkTextEncoding.
+
+        Text size is affected by SkMatrix and SkFont text size. Default text
+        size is 12 point.
 
         All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
-        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
-        filled 12 point black glyphs.
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By
+        default, draws filled black glyphs.
 
         @param text        character code points or glyphs drawn
         @param byteLength  byte length of text array
+        @param encoding    text encoding used in the text array
         @param x           start of text on x-axis
         @param y           start of text on y-axis
-        @param paint       text size, blend, color, and so on, used to draw
+        @param font        typeface, text size and so, used to describe the text
+        @param paint       blend, color, and so on, used to draw
     */
-    void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
-                  const SkPaint& paint);
-
-    /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix, and
-        SkPaint paint.
-
-        string meaning depends on SkPaint::TextEncoding; by default, strings are encoded
-        as UTF-8. Other values of SkPaint::TextEncoding are unlikely to produce the desired
-        results, since zero bytes may be embedded in the string.
-
-        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default
-        string draws left to right, positioning the first glyph left side bearing at x
-        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.
+    void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
+                        SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint);
+
+    /** Experimental.
+
+        Draws null terminated string, with origin at (x, y), using clip, SkMatrix,
+        SkFont font, and SkPaint paint.
+
+        This function uses the default character-to-glyph mapping from the
+        SkTypeface in font.  It does not perform typeface fallback for
+        characters not found in the SkTypeface.  It does not perform kerning;
+        glyphs are positioned based on their default advances.
+
+        String str is encoded as UTF-8.
+
+        Text size is affected by SkMatrix and font text size. Default text
+        size is 12 point.
 
         All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
-        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
-        filled 12 point black glyphs.
-
-        @param string  character code points or glyphs drawn,
-                       ending with a char value of zero
-        @param x       start of string on x-axis
-        @param y       start of string on y-axis
-        @param paint   text size, blend, color, and so on, used to draw
-    */
-    void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint) {
-        if (!string) {
-            return;
-        }
-        this->drawText(string, strlen(string), x, y, paint);
-    }
-
-    /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix, and
-        SkPaint paint.
-
-        string meaning depends on SkPaint::TextEncoding; by default, strings are encoded
-        as UTF-8. Other values of SkPaint::TextEncoding are unlikely to produce the desired
-        results, since zero bytes may be embedded in the string.
-
-        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default
-        string draws left to right, positioning the first glyph left side bearing at x
-        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.
-
-        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
-        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
-        filled 12 point black glyphs.
-
-        @param string  character code points or glyphs drawn,
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By
+        default, draws filled black glyphs.
+
+        @param str     character code points drawn,
                        ending with a char value of zero
         @param x       start of string on x-axis
         @param y       start of string on y-axis
-        @param paint   text size, blend, color, and so on, used to draw
+        @param font    typeface, text size and so, used to describe the text
+        @param paint   blend, color, and so on, used to draw
     */
-    void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint);
-
-    /** Draws each glyph in text with the origin in pos array, using clip, SkMatrix, and
-        SkPaint paint. The number of entries in pos array must match the number of glyphs
-        described by byteLength of text.
-
-        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as
-        UTF-8. pos elements meaning depends on SkPaint vertical text; by default
-        glyph left side bearing and baseline are relative to SkPoint in pos array.
-        Text size is affected by SkMatrix and SkPaint text size.
+    void drawString(const char str[], SkScalar x, SkScalar y, const SkFont& font,
+                    const SkPaint& paint) {
+        this->drawSimpleText(str, strlen(str), kUTF8_SkTextEncoding, x, y, font, paint);
+    }
+
+    /** Experimental.
+
+        Draws SkString, with origin at (x, y), using clip, SkMatrix, SkFont font,
+        and SkPaint paint.
+
+        This function uses the default character-to-glyph mapping from the
+        SkTypeface in font.  It does not perform typeface fallback for
+        characters not found in the SkTypeface.  It does not perform kerning;
+        glyphs are positioned based on their default advances.
+
+        SkString str is encoded as UTF-8.
+
+        Text size is affected by SkMatrix and SkFont text size. Default text
+        size is 12 point.
 
         All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
-        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
-        filled 12 point black glyphs.
-
-        Layout engines such as Harfbuzz typically position each glyph
-        rather than using the font advance widths.
-
-        @param text        character code points or glyphs drawn
-        @param byteLength  byte length of text array
-        @param pos         array of glyph origins
-        @param paint       text size, blend, color, and so on, used to draw
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By
+        default, draws filled black glyphs.
+
+        @param str     character code points drawn,
+                       ending with a char value of zero
+        @param x       start of string on x-axis
+        @param y       start of string on y-axis
+        @param font    typeface, text size and so, used to describe the text
+        @param paint   blend, color, and so on, used to draw
     */
-    void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
-                     const SkPaint& paint);
-
-    /** Draws each glyph in text with its (x, y) origin composed from xpos array and
-        constY, using clip, SkMatrix, and SkPaint paint. The number of entries in xpos array
-        must match the number of glyphs described by byteLength of text.
-
-        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as
-        UTF-8. xpos elements meaning depends on SkPaint vertical text;
-        by default each glyph left side bearing is positioned at an xpos element and
-        its baseline is positioned at constY. Text size is affected by SkMatrix and
-        SkPaint text size.
-
-        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
-        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
-        filled 12 point black glyphs.
-
-        Layout engines such as Harfbuzz typically position each glyph
-        rather than using the font advance widths if all glyphs share the same
-        baseline.
-
-        @param text        character code points or glyphs drawn
-        @param byteLength  byte length of text array
-        @param xpos        array of x-axis positions, used to position each glyph
-        @param constY      shared y-axis value for all of x-axis positions
-        @param paint       text size, blend, color, and so on, used to draw
-    */
-    void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
-                      const SkPaint& paint);
-
-    /** Draws text, transforming each glyph by the corresponding SkRSXform,
-        using clip, SkMatrix, and SkPaint paint.
-
-        SkRSXform xform array specifies a separate square scale, rotation, and translation
-        for each glyph. xform does not affect paint SkShader.
-
-        Optional SkRect cullRect is a conservative bounds of text, taking into account
-        SkRSXform and paint. If cullRect is outside of clip, canvas can skip drawing.
-
-        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
-        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
-        filled 12 point black glyphs.
-
-        @param text        character code points or glyphs drawn
-        @param byteLength  byte length of text array
-        @param xform       SkRSXform rotates, scales, and translates each glyph individually
-        @param cullRect    SkRect bounds of text for efficient clipping; or nullptr
-        @param paint       text size, blend, color, and so on, used to draw
-    */
-    void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
-                         const SkRect* cullRect, const SkPaint& paint);
+    void drawString(const SkString& str, SkScalar x, SkScalar y, const SkFont& font,
+                    const SkPaint& paint) {
+        this->drawSimpleText(str.c_str(), str.size(), kUTF8_SkTextEncoding, x, y, font, paint);
+    }
 
     /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
 
         blob contains glyphs, their positions, and paint attributes specific to text:
         SkTypeface, SkPaint text size, SkPaint text scale x,
         SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
         SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
         and SkPaint subpixel text.
 
-        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.
+        SkTextEncoding must be set to kGlyphID_SkTextEncoding.
 
         Elements of paint: anti-alias, SkBlendMode, color including alpha,
         SkColorFilter, SkPaint dither, SkDrawLooper, SkMaskFilter, SkPathEffect, SkShader, and
         SkPaint::Style; apply to blob. If SkPaint contains SkPaint::kStroke_Style:
         SkPaint miter limit, SkPaint::Cap, SkPaint::Join, and SkPaint stroke width;
         apply to SkPath created from blob.
 
         @param blob   glyphs, positions, and their paints' text size, typeface, and so on
@@ -1992,17 +1964,17 @@ public:
     /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
 
         blob contains glyphs, their positions, and paint attributes specific to text:
         SkTypeface, SkPaint text size, SkPaint text scale x,
         SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
         SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
         and SkPaint subpixel text.
 
-        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.
+        SkTextEncoding must be set to kGlyphID_SkTextEncoding.
 
         Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter,
         SkImageFilter, and SkDrawLooper; apply to blob.
 
         @param blob   glyphs, positions, and their paints' text size, typeface, and so on
         @param x      horizontal offset applied to blob
         @param y      vertical offset applied to blob
         @param paint  blend, color, stroking, and so on, used to draw
@@ -2291,32 +2263,32 @@ public:
 
         @param drawable  custom struct encapsulating drawing commands
         @param x         offset into SkCanvas writable pixels on x-axis
         @param y         offset into SkCanvas writable pixels on y-axis
     */
     void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y);
 
     /** Associates SkRect on SkCanvas with an annotation; a key-value pair, where the key is
-        a null-terminated utf8 string, and optional value is stored as SkData.
+        a null-terminated UTF-8 string, and optional value is stored as SkData.
 
         Only some canvas implementations, such as recording to SkPicture, or drawing to
-        document pdf, use annotations.
+        document PDF, use annotations.
 
         @param rect   SkRect extent of canvas to annotate
         @param key    string used for lookup
         @param value  data holding value stored in annotation
     */
     void drawAnnotation(const SkRect& rect, const char key[], SkData* value);
 
     /** Associates SkRect on SkCanvas when an annotation; a key-value pair, where the key is
-        a null-terminated utf8 string, and optional value is stored as SkData.
+        a null-terminated UTF-8 string, and optional value is stored as SkData.
 
         Only some canvas implementations, such as recording to SkPicture, or drawing to
-        document pdf, use annotations.
+        document PDF, use annotations.
 
         @param rect   SkRect extent of canvas to annotate
         @param key    string used for lookup
         @param value  data holding value stored in annotation
     */
     void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
         this->drawAnnotation(rect, key, value.get());
     }
@@ -2387,46 +2359,41 @@ protected:
         kNoLayer_SaveLayerStrategy,
     };
 
     virtual void willSave() {}
     // Overriders should call the corresponding INHERITED method up the inheritance chain.
     virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& ) {
         return kFullLayer_SaveLayerStrategy;
     }
+    // returns true if we should actually perform the saveBehind, or false if we should just save.
+    virtual bool onDoSaveBehind(const SkRect*) { return true; }
     virtual void willRestore() {}
     virtual void didRestore() {}
     virtual void didConcat(const SkMatrix& ) {}
     virtual void didSetMatrix(const SkMatrix& ) {}
     virtual void didTranslate(SkScalar dx, SkScalar dy) {
         this->didConcat(SkMatrix::MakeTrans(dx, dy));
     }
 
     // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to
     // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using
     // that mechanism  will be required to implement the new function.
     virtual void onDrawPaint(const SkPaint& paint);
     virtual void onDrawRect(const SkRect& rect, const SkPaint& paint);
+    virtual void onDrawEdgeAARect(const SkRect& rect, QuadAAFlags edgeAA, SkColor color,
+                                  SkBlendMode mode);
     virtual void onDrawRRect(const SkRRect& rrect, const SkPaint& paint);
     virtual void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
     virtual void onDrawOval(const SkRect& rect, const SkPaint& paint);
     virtual void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
                            bool useCenter, const SkPaint& paint);
     virtual void onDrawPath(const SkPath& path, const SkPaint& paint);
     virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
 
-    virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
-                            SkScalar y, const SkPaint& paint);
-    virtual void onDrawPosText(const void* text, size_t byteLength,
-                               const SkPoint pos[], const SkPaint& paint);
-    virtual void onDrawPosTextH(const void* text, size_t byteLength,
-                                const SkScalar xpos[], SkScalar constY,
-                                const SkPaint& paint);
-    virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
-                                   const SkRect* cullRect, const SkPaint& paint);
     virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
                                 const SkPaint& paint);
 
     virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
                            const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
     virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
                               const SkPaint& paint);
 
@@ -2441,16 +2408,19 @@ protected:
     virtual void onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint);
     virtual void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
                                  const SkPaint* paint, SrcRectConstraint constraint);
     virtual void onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
                                  const SkPaint* paint);
     virtual void onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
                                     const SkPaint* paint);
 
+    virtual void onDrawImageSet(const ImageSetEntry imageSet[], int count, SkFilterQuality,
+                                SkBlendMode);
+
     virtual void onDrawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy,
                               const SkPaint* paint);
     virtual void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
                                   const SkPaint* paint, SrcRectConstraint constraint);
     virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
                                   const SkPaint* paint);
     virtual void onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
                                      const SkRect& dst, const SkPaint* paint);
@@ -2562,17 +2532,16 @@ private:
 
     intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
     intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
 
     const SkSurfaceProps fProps;
 
     int         fSaveCount;         // value returned by getSaveCount()
 
-    SkMetaData* fMetaData;
     std::unique_ptr<SkRasterHandleAllocator> fAllocator;
 
     SkSurface_Base*  fSurfaceBase;
     SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
     void setSurfaceBase(SkSurface_Base* sb) {
         fSurfaceBase = sb;
     }
     friend class SkSurface_Base;
@@ -2589,29 +2558,39 @@ private:
     friend class SkDrawIter;        // needs setupDrawForLayerDevice()
     friend class AutoDrawLooper;
     friend class SkDebugCanvas;     // needs experimental fAllowSimplifyClip
     friend class SkSurface_Raster;  // needs getDevice()
     friend class SkNoDrawCanvas;    // needs resetForNextPicture()
     friend class SkPictureRecord;   // predrawNotify (why does it need it? <reed>)
     friend class SkOverdrawCanvas;
     friend class SkRasterHandleAllocator;
-
+    friend class ClipTileRenderer;  // GM needs getTopDevice() until API is in SkCanvas
 protected:
     // For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
     SkCanvas(const SkIRect& bounds);
 private:
     SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>,
              SkRasterHandleAllocator::Handle);
 
     SkCanvas(SkCanvas&&) = delete;
     SkCanvas(const SkCanvas&) = delete;
     SkCanvas& operator=(SkCanvas&&) = delete;
     SkCanvas& operator=(const SkCanvas&) = delete;
 
+    /** Experimental
+     *  Saves the specified subset of the current pixels in the current layer,
+     *  and then clears those pixels to transparent black.
+     *  Restores the pixels on restore() by drawing them in SkBlendMode::kDstOver.
+     *
+     *  @param subset   conservative bounds of the area to be saved / restored.
+     *  @return depth of save state stack before this call was made.
+     */
+    int only_axis_aligned_saveBehind(const SkRect* subset);
+
     void resetForNextPicture(const SkIRect& bounds);
 
     // needs gettotalclip()
     friend class SkCanvasStateUtils;
 
     // call this each time we attach ourselves to a device
     //  - constructor
     //  - internalSaveLayer
@@ -2625,16 +2604,17 @@ private:
      */
     SkIRect getTopLayerBounds() const;
 
     void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
                                 const SkRect& dst, const SkPaint* paint,
                                 SrcRectConstraint);
     void internalDrawPaint(const SkPaint& paint);
     void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
+    void internalSaveBehind(const SkRect*);
     void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, SkImage* clipImage,
                             const SkMatrix& clipMatrix);
 
     // shared by save() and saveLayer()
     void internalSave();
     void internalRestore();
 
     /*
@@ -2695,17 +2675,17 @@ private:
 /** \class SkAutoCanvasRestore
     Stack helper class calls SkCanvas::restoreToCount when SkAutoCanvasRestore
     goes out of scope. Use this to guarantee that the canvas is restored to a known
     state.
 */
 class SkAutoCanvasRestore {
 public:
 
-    /** Preserves SkCanvas save count. Optionally saves SkCanvas clip and SkCanvas matrix.
+    /** Preserves SkCanvas::save() count. Optionally saves SkCanvas clip and SkCanvas matrix.
 
         @param canvas  SkCanvas to guard
         @param doSave  call SkCanvas::save()
         @return        utility to restore SkCanvas state on destructor
     */
     SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
         if (fCanvas) {
             fSaveCount = canvas->getSaveCount();
@@ -2720,17 +2700,17 @@ public:
     */
     ~SkAutoCanvasRestore() {
         if (fCanvas) {
             fCanvas->restoreToCount(fSaveCount);
         }
     }
 
     /** Restores SkCanvas to saved state immediately. Subsequent calls and
-        ~SkAutoCanvasRestore have no effect.
+        ~SkAutoCanvasRestore() have no effect.
     */
     void restore() {
         if (fCanvas) {
             fCanvas->restoreToCount(fSaveCount);
             fCanvas = nullptr;
         }
     }
 
@@ -2738,11 +2718,13 @@ private:
     SkCanvas*   fCanvas;
     int         fSaveCount;
 
     SkAutoCanvasRestore(SkAutoCanvasRestore&&) = delete;
     SkAutoCanvasRestore(const SkAutoCanvasRestore&) = delete;
     SkAutoCanvasRestore& operator=(SkAutoCanvasRestore&&) = delete;
     SkAutoCanvasRestore& operator=(const SkAutoCanvasRestore&) = delete;
 };
+
+// Private
 #define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
 
 #endif
--- a/gfx/skia/skia/include/core/SkCanvasVirtualEnforcer.h
+++ b/gfx/skia/skia/include/core/SkCanvasVirtualEnforcer.h
@@ -25,24 +25,16 @@ protected:
     void onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
                       const SkPaint& paint) override = 0;
     void onDrawOval(const SkRect& rect, const SkPaint& paint) override = 0;
     void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
                    const SkPaint& paint) override = 0;
     void onDrawPath(const SkPath& path, const SkPaint& paint) override = 0;
     void onDrawRegion(const SkRegion& region, const SkPaint& paint) override = 0;
 
-    void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
-                    const SkPaint& paint) override = 0;
-    void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
-                       const SkPaint& paint) override = 0;
-    void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
-                        SkScalar constY, const SkPaint& paint) override = 0;
-    void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
-                           const SkRect* cullRect, const SkPaint& paint) override = 0;
     void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
                         const SkPaint& paint) override = 0;
 
     void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
                      const SkPoint texCoords[4], SkBlendMode mode,
                      const SkPaint& paint) override = 0;
     void onDrawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
                       const SkPaint& paint) override = 0;
@@ -53,16 +45,30 @@ protected:
                      const SkPaint* paint) override = 0;
     void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
                          const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) override = 0;
     void onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
                          const SkPaint* paint) override = 0;
     void onDrawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice,
                             const SkRect& dst, const SkPaint* paint) override = 0;
 
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+    // This is under active development for Chrome and not used in Android. Hold off on adding
+    // implementations in Android's SkCanvas subclasses until this stabilizes.
+    void onDrawImageSet(const SkCanvas::ImageSetEntry[], int count, SkFilterQuality,
+                        SkBlendMode) override {};
+    void onDrawEdgeAARect(const SkRect& rect, SkCanvas::QuadAAFlags edgeAA, SkColor color,
+                          SkBlendMode mode) override {};
+#else
+    void onDrawImageSet(const SkCanvas::ImageSetEntry[], int count, SkFilterQuality,
+                        SkBlendMode) override = 0;
+    void onDrawEdgeAARect(const SkRect& rect, SkCanvas::QuadAAFlags edgeAA, SkColor color,
+                          SkBlendMode mode) override = 0;
+#endif
+
     void onDrawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy,
                       const SkPaint* paint) override = 0;
     void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
                           const SkPaint* paint,
                           SkCanvas::SrcRectConstraint constraint) override = 0;
     void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
                           const SkPaint* paint) override = 0;
     void onDrawBitmapLattice(const SkBitmap& bitmap, const SkCanvas::Lattice& lattice,
--- a/gfx/skia/skia/include/core/SkColor.h
+++ b/gfx/skia/skia/include/core/SkColor.h
@@ -223,78 +223,176 @@ SK_API SkPMColor SkPreMultiplyARGB(U8CPU
 /** Returns pmcolor closest to color c. Multiplies c RGB components by the c alpha,
     and arranges the bytes to match the format of kN32_SkColorType.
 
     @param c  unpremultiplied ARGB color
     @return   premultiplied color
 */
 SK_API SkPMColor SkPreMultiplyColor(SkColor c);
 
+/** \struct SkRGBA4f
+    RGBA color value, holding four floating point components. Color components are always in
+    a known order. kAT determines if the SkRGBA4f's R, G, and B components are premultiplied
+    by alpha or not.
+
+    Skia's public API always uses unpremultiplied colors, which can be stored as
+    SkRGBA4f<kUnpremul_SkAlphaType>. For convenience, this type can also be referred to
+    as SkColor4f.
+*/
 template <SkAlphaType kAT>
 struct SkRGBA4f {
-    float fR;
-    float fG;
-    float fB;
-    float fA;
+    float fR;  //!< red component
+    float fG;  //!< green component
+    float fB;  //!< blue component
+    float fA;  //!< alpha component
 
+    /** Compares SkRGBA4f with other, and returns true if all components are equal.
+
+        @param other  SkRGBA4f to compare
+        @return       true if SkRGBA4f equals other
+    */
     bool operator==(const SkRGBA4f& other) const {
         return fA == other.fA && fR == other.fR && fG == other.fG && fB == other.fB;
     }
+
+    /** Compares SkRGBA4f with other, and returns true if not all components are equal.
+
+        @param other  SkRGBA4f to compare
+        @return       true if SkRGBA4f is not equal to other
+    */
     bool operator!=(const SkRGBA4f& other) const {
         return !(*this == other);
     }
 
+    /** Returns SkRGBA4f multiplied by scale.
+
+        @param scale  value to multiply by
+        @return       SkRGBA4f as (fR * scale, fG * scale, fB * scale, fA * scale)
+    */
     SkRGBA4f operator*(float scale) const {
         return { fR * scale, fG * scale, fB * scale, fA * scale };
     }
 
+    /** Returns SkRGBA4f multiplied component-wise by scale.
+
+        @param scale  SkRGBA4f to multiply by
+        @return       SkRGBA4f as (fR * scale.fR, fG * scale.fG, fB * scale.fB, fA * scale.fA)
+    */
     SkRGBA4f operator*(const SkRGBA4f& scale) const {
         return { fR * scale.fR, fG * scale.fG, fB * scale.fB, fA * scale.fA };
     }
 
+    /** Returns a pointer to components of SkRGBA4f, for array access.
+
+        @return       pointer to array [fR, fG, fB, fA]
+    */
     const float* vec() const { return &fR; }
-          float* vec()       { return &fR; }
+
+    /** Returns a pointer to components of SkRGBA4f, for array access.
 
+        @return       pointer to array [fR, fG, fB, fA]
+    */
+    float* vec() { return &fR; }
+
+    /** Returns one component. Asserts if index is out of range and SK_DEBUG is defined.
+
+        @param index  one of: 0 (fR), 1 (fG), 2 (fB), 3 (fA)
+        @return       value corresponding to index
+    */
     float operator[](int index) const {
         SkASSERT(index >= 0 && index < 4);
         return this->vec()[index];
     }
 
+    /** Returns one component. Asserts if index is out of range and SK_DEBUG is defined.
+
+        @param index  one of: 0 (fR), 1 (fG), 2 (fB), 3 (fA)
+        @return       value corresponding to index
+    */
     float& operator[](int index) {
         SkASSERT(index >= 0 && index < 4);
         return this->vec()[index];
     }
 
+    /** Returns true if SkRGBA4f is an opaque color. Asserts if fA is out of range and
+        SK_DEBUG is defined.
+
+        @return       true if SkRGBA4f is opaque
+    */
     bool isOpaque() const {
         SkASSERT(fA <= 1.0f && fA >= 0.0f);
         return fA == 1.0f;
     }
 
-    static SkRGBA4f Pin(float r, float g, float b, float a);  // impl. depends on kAT
-    SkRGBA4f pin() const { return Pin(fR, fG, fB, fA); }
+    /** Returns true if all channels are in [0, 1]. */
+    bool fitsInBytes() const {
+        SkASSERT(fA >= 0.0f && fA <= 1.0f);
+        return fR >= 0.0f && fR <= 1.0f &&
+               fG >= 0.0f && fG <= 1.0f &&
+               fB >= 0.0f && fB <= 1.0f;
+    }
+
+    /** Returns closest SkRGBA4f to SkColor. Only allowed if SkRGBA4f is unpremultiplied.
 
-    static SkRGBA4f FromColor(SkColor);  // impl. depends on kAT
+        @param color   Color with Alpha, red, blue, and green components
+        @return        SkColor as SkRGBA4f
+    */
+    static SkRGBA4f FromColor(SkColor color);  // impl. depends on kAT
+
+    /** Returns closest SkColor to SkRGBA4f. Only allowed if SkRGBA4f is unpremultiplied.
+
+        @return       color as SkColor
+    */
     SkColor toSkColor() const;  // impl. depends on kAT
 
+    /** Returns closest SkRGBA4f to SkPMColor. Only allowed if SkRGBA4f is premultiplied.
+
+        @return        SkPMColor as SkRGBA4f
+    */
     static SkRGBA4f FromPMColor(SkPMColor);  // impl. depends on kAT
 
+    /** Returns SkRGBA4f premultiplied by alpha. Asserts at compile time if SkRGBA4f is
+        already premultiplied.
+
+        @return       premultiplied color
+    */
     SkRGBA4f<kPremul_SkAlphaType> premul() const {
         static_assert(kAT == kUnpremul_SkAlphaType, "");
         return { fR * fA, fG * fA, fB * fA, fA };
     }
 
+    /** Returns SkRGBA4f unpremultiplied by alpha. Asserts at compile time if SkRGBA4f is
+        already unpremultiplied.
+
+        @return       unpremultiplied color
+    */
     SkRGBA4f<kUnpremul_SkAlphaType> unpremul() const {
         static_assert(kAT == kPremul_SkAlphaType, "");
 
         if (fA == 0.0f) {
             return { 0, 0, 0, 0 };
         } else {
             float invAlpha = 1 / fA;
             return { fR * invAlpha, fG * invAlpha, fB * invAlpha, fA };
         }
     }
+
+    // This produces bytes in RGBA order (eg GrColor). Impl. is the same, regardless of kAT
+    uint32_t toBytes_RGBA() const;
+    static SkRGBA4f FromBytes_RGBA(uint32_t color);
+
+    SkRGBA4f makeOpaque() const {
+        return { fR, fG, fB, 1.0f };
+    }
 };
 
+/** \struct SkColor4f
+    RGBA color value, holding four floating point components. Color components are always in
+    a known order, and are unpremultiplied.
+
+    This is a specialization of SkRGBA4f. For details, @see SkRGBA4f.
+*/
 using SkColor4f = SkRGBA4f<kUnpremul_SkAlphaType>;
+
 template <> SK_API SkColor4f SkColor4f::FromColor(SkColor);
 template <> SK_API SkColor   SkColor4f::toSkColor() const;
 
 #endif
--- a/gfx/skia/skia/include/core/SkColorFilter.h
+++ b/gfx/skia/skia/include/core/SkColorFilter.h
@@ -8,19 +8,19 @@
 #ifndef SkColorFilter_DEFINED
 #define SkColorFilter_DEFINED
 
 #include "SkBlendMode.h"
 #include "SkColor.h"
 #include "SkFlattenable.h"
 #include "SkRefCnt.h"
 
-class GrContext;
 class GrColorSpaceInfo;
 class GrFragmentProcessor;
+class GrRecordingContext;
 class SkArenaAlloc;
 class SkBitmap;
 class SkColorSpace;
 class SkColorSpaceXformer;
 class SkRasterPipeline;
 class SkString;
 
 /**
@@ -115,35 +115,46 @@ public:
     /** Construct a colorfilter that applies the srgb gamma curve to the RGB channels */
     static sk_sp<SkColorFilter> MakeLinearToSRGBGamma();
 
     /** Construct a colorfilter that applies the inverse of the srgb gamma curve to the
      *  RGB channels
      */
     static sk_sp<SkColorFilter> MakeSRGBToLinearGamma();
 
+    /**
+     *  Returns a new filter that returns the weighted average between the outputs of
+     *  two other filters. If either is null, then it is treated as an identity filter.
+     *
+     *  result = cf0(color) * (1 - weight) + cf1(color) * weight
+     *
+     *  If both filters are null, or if weight is NaN, then null is returned.
+     */
+    static sk_sp<SkColorFilter> MakeMixer(sk_sp<SkColorFilter> cf0, sk_sp<SkColorFilter> cf1,
+                                          float weight);
+
 #if SK_SUPPORT_GPU
     /**
      *  A subclass may implement this factory function to work with the GPU backend. It returns
      *  a GrFragmentProcessor that implemets the color filter in GPU shader code.
      *
      *  The fragment processor receives a premultiplied input color and produces a premultiplied
      *  output color.
      *
      *  A null return indicates that the color filter isn't implemented for the GPU backend.
      */
     virtual std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
-            GrContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const;
+            GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const;
 #endif
 
     bool affectsTransparentBlack() const {
         return this->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
     }
 
-    static void InitializeFlattenables();
+    static void RegisterFlattenables();
 
     static SkFlattenable::Type GetFlattenableType() {
         return kSkColorFilter_Type;
     }
 
     SkFlattenable::Type getFlattenableType() const override {
         return kSkColorFilter_Type;
     }
--- a/gfx/skia/skia/include/core/SkColorPriv.h
+++ b/gfx/skia/skia/include/core/SkColorPriv.h
@@ -40,32 +40,57 @@ static inline U8CPU SkUnitScalarClampToB
 #define SK_B32_BITS     8
 
 #define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
 #define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
 #define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
 #define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
 
 /*
- *  Skia's 32bit backend only supports 1 sizzle order at a time (compile-time).
+ *  Skia's 32bit backend only supports 1 swizzle order at a time (compile-time).
  *  This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B.
  *
  *  For easier compatibility with Skia's GPU backend, we further restrict these
  *  to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
  *  not directly correspond to the same shift-order, since we have to take endianess
  *  into account.
  *
  *  Here we enforce this constraint.
  */
 
 #define SK_RGBA_R32_SHIFT   0
 #define SK_RGBA_G32_SHIFT   8
 #define SK_RGBA_B32_SHIFT   16
 #define SK_RGBA_A32_SHIFT   24
 
+#define SK_BGRA_B32_SHIFT   0
+#define SK_BGRA_G32_SHIFT   8
+#define SK_BGRA_R32_SHIFT   16
+#define SK_BGRA_A32_SHIFT   24
+
+#if defined(SK_PMCOLOR_IS_RGBA) || defined(SK_PMCOLOR_IS_BGRA)
+    #error "Configure PMCOLOR by setting SK_R32_SHIFT, etc"
+#endif
+
+// Deduce which SK_PMCOLOR_IS_ to define from the _SHIFT defines
+
+#if (SK_A32_SHIFT == SK_RGBA_A32_SHIFT && \
+     SK_R32_SHIFT == SK_RGBA_R32_SHIFT && \
+     SK_G32_SHIFT == SK_RGBA_G32_SHIFT && \
+     SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
+    #define SK_PMCOLOR_IS_RGBA
+#elif (SK_A32_SHIFT == SK_BGRA_A32_SHIFT && \
+       SK_R32_SHIFT == SK_BGRA_R32_SHIFT && \
+       SK_G32_SHIFT == SK_BGRA_G32_SHIFT && \
+       SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
+    #define SK_PMCOLOR_IS_BGRA
+#else
+    #error "need 32bit packing to be either RGBA or BGRA"
+#endif
+
 #define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
 #define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
 #define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
 #define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
 
 #define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
 #define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
 #define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
@@ -118,44 +143,9 @@ static SK_ALWAYS_INLINE uint32_t SkAlpha
     uint32_t ag = ((c >> 8) & mask) * scale;
     return (rb & mask) | (ag & ~mask);
 }
 
 static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
     return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
 }
 
-////////////////////////////////////////////////////////////////////////////////////////////
-// Convert a 16bit pixel to a 32bit pixel
-
-#define SK_R16_BITS     5
-#define SK_G16_BITS     6
-#define SK_B16_BITS     5
-
-#define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)
-#define SK_G16_SHIFT    (SK_B16_BITS)
-#define SK_B16_SHIFT    0
-
-#define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)
-#define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)
-#define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)
-
-#define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
-#define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
-#define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
-
-static inline unsigned SkR16ToR32(unsigned r) {
-    return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
-}
-
-static inline unsigned SkG16ToG32(unsigned g) {
-    return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
-}
-
-static inline unsigned SkB16ToB32(unsigned b) {
-    return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
-}
-
-#define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))
-#define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))
-#define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))
-
 #endif
--- a/gfx/skia/skia/include/core/SkColorSpace.h
+++ b/gfx/skia/skia/include/core/SkColorSpace.h
@@ -3,30 +3,24 @@
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkColorSpace_DEFINED
 #define SkColorSpace_DEFINED
 
+#include "../private/SkFixed.h"
 #include "../private/SkOnce.h"
+#include "../../third_party/skcms/skcms.h"
 #include "SkMatrix44.h"
 #include "SkRefCnt.h"
 #include <memory>
 
 class SkData;
-struct skcms_ICCProfile;
-
-enum SkGammaNamed {
-    kLinear_SkGammaNamed,
-    kSRGB_SkGammaNamed,
-    k2Dot2Curve_SkGammaNamed,
-    kNonStandard_SkGammaNamed,
-};
 
 /**
  *  Describes a color gamut with primaries and a white point.
  */
 struct SK_API SkColorSpacePrimaries {
     float fRX;
     float fRY;
     float fGX;
@@ -35,118 +29,129 @@ struct SK_API SkColorSpacePrimaries {
     float fBY;
     float fWX;
     float fWY;
 
     /**
      *  Convert primaries and a white point to a toXYZD50 matrix, the preferred color gamut
      *  representation of SkColorSpace.
      */
-    bool toXYZD50(SkMatrix44* toXYZD50) const;
+    bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
 };
 
-/**
- *  Contains the coefficients for a common transfer function equation, specified as
- *  a transformation from a curved space to linear.
- *
- *  LinearVal = sign(InputVal) * (  C*|InputVal| + F       ), for 0.0f <= |InputVal| <  D
- *  LinearVal = sign(InputVal) * ( (A*|InputVal| + B)^G + E), for D    <= |InputVal|
- *
- *  Function must be positive and increasing.
- */
-struct SK_API SkColorSpaceTransferFn {
-    float fG;
-    float fA;
-    float fB;
-    float fC;
-    float fD;
-    float fE;
-    float fF;
-};
+namespace SkNamedTransferFn {
+
+// Like SkNamedGamut::kSRGB, keeping this bitwise exactly the same as skcms makes things fastest.
+static constexpr skcms_TransferFunction kSRGB =
+    { 2.4f, (float)(1/1.055), (float)(0.055/1.055), (float)(1/12.92), 0.04045f, 0.0f, 0.0f };
+
+static constexpr skcms_TransferFunction k2Dot2 =
+    { 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+
+static constexpr skcms_TransferFunction kLinear =
+    { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+
+}
+
+namespace SkNamedGamut {
+
+static constexpr skcms_Matrix3x3 kSRGB = {{
+    // ICC fixed-point (16.16) representation, taken from skcms. Please keep them exactly in sync.
+    // 0.436065674f, 0.385147095f, 0.143066406f,
+    // 0.222488403f, 0.716873169f, 0.060607910f,
+    // 0.013916016f, 0.097076416f, 0.714096069f,
+    { SkFixedToFloat(0x6FA2), SkFixedToFloat(0x6299), SkFixedToFloat(0x24A0) },
+    { SkFixedToFloat(0x38F5), SkFixedToFloat(0xB785), SkFixedToFloat(0x0F84) },
+    { SkFixedToFloat(0x0390), SkFixedToFloat(0x18DA), SkFixedToFloat(0xB6CF) },
+}};
+
+static constexpr skcms_Matrix3x3 kAdobeRGB = {{
+    // ICC fixed-point (16.16) repesentation of:
+    // 0.60974, 0.20528, 0.14919,
+    // 0.31111, 0.62567, 0.06322,
+    // 0.01947, 0.06087, 0.74457,
+    { SkFixedToFloat(0x9c18), SkFixedToFloat(0x348d), SkFixedToFloat(0x2631) },
+    { SkFixedToFloat(0x4fa5), SkFixedToFloat(0xa02c), SkFixedToFloat(0x102f) },
+    { SkFixedToFloat(0x04fc), SkFixedToFloat(0x0f95), SkFixedToFloat(0xbe9c) },
+}};
+
+static constexpr skcms_Matrix3x3 kDCIP3 = {{
+    {  0.515102f,   0.291965f,  0.157153f  },
+    {  0.241182f,   0.692236f,  0.0665819f },
+    { -0.00104941f, 0.0418818f, 0.784378f  },
+}};
+
+static constexpr skcms_Matrix3x3 kRec2020 = {{
+    {  0.673459f,   0.165661f,  0.125100f  },
+    {  0.279033f,   0.675338f,  0.0456288f },
+    { -0.00193139f, 0.0299794f, 0.797162f  },
+}};
+
+static constexpr skcms_Matrix3x3 kXYZ = {{
+    { 1.0f, 0.0f, 0.0f },
+    { 0.0f, 1.0f, 0.0f },
+    { 0.0f, 0.0f, 1.0f },
+}};
+
+}
 
 class SK_API SkColorSpace : public SkNVRefCnt<SkColorSpace> {
 public:
     /**
      *  Create the sRGB color space.
      */
     static sk_sp<SkColorSpace> MakeSRGB();
 
     /**
-     *  Colorspace with the sRGB primaries, but a linear (1.0) gamma. Commonly used for
-     *  half-float surfaces, and high precision individual colors (gradient stops, etc...)
+     *  Colorspace with the sRGB primaries, but a linear (1.0) gamma.
      */
     static sk_sp<SkColorSpace> MakeSRGBLinear();
 
-    enum RenderTargetGamma : uint8_t {
-        kLinear_RenderTargetGamma,
-
-        /**
-         *  Transfer function is the canonical sRGB curve, which has a short linear segment
-         *  followed by a 2.4f exponential.
-         */
-        kSRGB_RenderTargetGamma,
-    };
-
-    enum Gamut {
-        kSRGB_Gamut,
-        kAdobeRGB_Gamut,
-        kDCIP3_D65_Gamut,
-        kRec2020_Gamut,
-    };
-
     /**
-     *  Create an SkColorSpace from a transfer function and a color gamut.
-     *
-     *  Transfer function can be specified as an enum or as the coefficients to an equation.
-     *  Gamut can be specified as an enum or as the matrix transformation to XYZ D50.
+     *  Create an SkColorSpace from a transfer function and a row-major 3x3 transformation to XYZ.
      */
-    static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, Gamut gamut);
-    static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50);
-    static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs, Gamut gamut);
-    static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs,
-                                       const SkMatrix44& toXYZD50);
-
-    static sk_sp<SkColorSpace> MakeRGB(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50);
+    static sk_sp<SkColorSpace> MakeRGB(const skcms_TransferFunction& transferFn,
+                                       const skcms_Matrix3x3& toXYZ);
 
     /**
      *  Create an SkColorSpace from a parsed (skcms) ICC profile.
      */
     static sk_sp<SkColorSpace> Make(const skcms_ICCProfile&);
 
     /**
      *  Convert this color space to an skcms ICC profile struct.
      */
     void toProfile(skcms_ICCProfile*) const;
 
-    SkGammaNamed gammaNamed() const { return fGammaNamed; }
-
     /**
      *  Returns true if the color space gamma is near enough to be approximated as sRGB.
      */
-    bool gammaCloseToSRGB() const { return kSRGB_SkGammaNamed == fGammaNamed; }
+    bool gammaCloseToSRGB() const;
 
     /**
      *  Returns true if the color space gamma is linear.
      */
-    bool gammaIsLinear() const { return kLinear_SkGammaNamed == fGammaNamed; }
+    bool gammaIsLinear() const;
 
     /**
      *  If the transfer function can be represented as coefficients to the standard
      *  equation, returns true and sets |fn| to the proper values.
      *
      *  If not, returns false.
      */
-    bool isNumericalTransferFn(SkColorSpaceTransferFn* fn) const;
+    bool isNumericalTransferFn(skcms_TransferFunction* fn) const;
 
     /**
      *  Returns true and sets |toXYZD50| if the color gamut can be described as a matrix.
      *  Returns false otherwise.
      */
     bool toXYZD50(SkMatrix44* toXYZD50) const;
 
+    bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
+
     /**
      *  Returns a hash of the gamut transformation to XYZ D50. Allows for fast equality checking
      *  of gamuts, at the (very small) risk of collision.
      */
     uint32_t toXYZD50Hash() const { return fToXYZD50Hash; }
 
     /**
      *  Returns a color space with the same gamut as this one, but with a linear gamma.
@@ -211,23 +216,21 @@ public:
     void gamutTransformTo(const SkColorSpace* dst, float src_to_dst_row_major[9]) const;
 
     uint32_t transferFnHash() const { return fTransferFnHash; }
     uint64_t           hash() const { return (uint64_t)fTransferFnHash << 32 | fToXYZD50Hash; }
 
 private:
     friend class SkColorSpaceSingletonFactory;
 
-    SkColorSpace(SkGammaNamed gammaNamed,
-                 const float transferFn[7],
-                 const SkMatrix44& toXYZ);
+    SkColorSpace(const float transferFn[7],
+                 const skcms_Matrix3x3& toXYZ);
 
     void computeLazyDstFields() const;
 
-    SkGammaNamed                        fGammaNamed;         // TODO: 2-bit, pack tightly?  drop?
     uint32_t                            fTransferFnHash;
     uint32_t                            fToXYZD50Hash;
 
     float                               fTransferFn[7];
     float                               fToXYZD50_3x3[9];    // row-major
 
     mutable float                       fInvTransferFn[7];
     mutable float                       fFromXYZD50_3x3[9];  // row-major
new file mode 100644
--- /dev/null
+++ b/gfx/skia/skia/include/core/SkContourMeasure.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkContourMeasure_DEFINED
+#define SkContourMeasure_DEFINED
+
+#include "../private/SkNoncopyable.h"
+#include "../private/SkTDArray.h"
+#include "SkPath.h"
+#include "SkRefCnt.h"
+
+struct SkConic;
+
+class SK_API SkContourMeasure : public SkRefCnt {
+public:
+    /** Return the length of the contour.
+     */
+    SkScalar length() const { return fLength; }
+
+    /** Pins distance to 0 <= distance <= length(), and then computes the corresponding
+     *  position and tangent.
+     */
+    bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position,
+                                         SkVector* tangent) const;
+
+    enum MatrixFlags {
+        kGetPosition_MatrixFlag     = 0x01,
+        kGetTangent_MatrixFlag      = 0x02,
+        kGetPosAndTan_MatrixFlag    = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
+    };
+
+    /** Pins distance to 0 <= distance <= getLength(), and then computes
+     the corresponding matrix (by calling getPosTan).
+     Returns false if there is no path, or a zero-length path was specified, in which case
+     matrix is unchanged.
+     */
+    bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix,
+                                         MatrixFlags flags = kGetPosAndTan_MatrixFlag) const;
+
+    /** Given a start and stop distance, return in dst the intervening segment(s).
+     If the segment is zero-length, return false, else return true.
+     startD and stopD are pinned to legal values (0..getLength()). If startD > stopD
+     then return false (and leave dst untouched).
+     Begin the segment with a moveTo if startWithMoveTo is true
+     */
+    bool SK_WARN_UNUSED_RESULT getSegment(SkScalar startD, SkScalar stopD, SkPath* dst,
+                                          bool startWithMoveTo) const;
+
+    /** Return true if the contour is closed()
+     */
+    bool isClosed() const { return fIsClosed; }
+
+private:
+    struct Segment {
+        SkScalar    fDistance;  // total distance up to this point
+        unsigned    fPtIndex; // index into the fPts array
+        unsigned    fTValue : 30;
+        unsigned    fType : 2;  // actually the enum SkSegType
+        // See SkPathMeasurePriv.h
+
+        SkScalar getScalarT() const;
+
+        static const Segment* Next(const Segment* seg) {
+            unsigned ptIndex = seg->fPtIndex;
+            do {
+                ++seg;
+            } while (seg->fPtIndex == ptIndex);
+            return seg;
+        }
+
+    };
+
+    const SkTDArray<Segment>  fSegments;
+    const SkTDArray<SkPoint>  fPts; // Points used to define the segments
+
+    const SkScalar fLength;
+    const bool fIsClosed;
+
+    SkContourMeasure(SkTDArray<Segment>&& segs, SkTDArray<SkPoint>&& pts,
+                     SkScalar length, bool isClosed);
+    ~SkContourMeasure() override {}
+
+    const Segment* distanceToSegment(SkScalar distance, SkScalar* t) const;
+
+    friend class SkContourMeasureIter;
+};
+
+class SK_API SkContourMeasureIter : SkNoncopyable {
+public:
+    SkContourMeasureIter();
+    /**
+     *  Initialize the Iter with a path.
+     *  The parts of the path that are needed are copied, so the client is free to modify/delete
+     *  the path after this call.
+     */
+    SkContourMeasureIter(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
+    ~SkContourMeasureIter();
+
+    /**
+     *  Reset the Iter with a path.
+     *  The parts of the path that are needed are copied, so the client is free to modify/delete
+     *  the path after this call.
+     */
+    void reset(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
+
+    /**
+     *  Iterates through contours in path, returning a contour-measure object for each contour
+     *  in the path. Returns null when it is done.
+     *
+     *  This only returns non-zero length contours, where a contour is the segments between
+     *  a kMove_Verb and either ...
+     *      - the next kMove_Verb
+     *      - kClose_Verb (1 or more)
+     *      - kDone_Verb
+     *  If it encounters a zero-length contour, it is skipped.
+     */
+    sk_sp<SkContourMeasure> next();
+
+private:
+    SkPath::RawIter fIter;
+    SkPath          fPath;
+    SkScalar        fTolerance;
+    bool            fForceClosed;
+
+    // temporary
+    SkTDArray<SkContourMeasure::Segment>  fSegments;
+    SkTDArray<SkPoint>  fPts; // Points used to define the segments
+
+    SkContourMeasure* buildSegments();
+
+    SkScalar compute_line_seg(SkPoint p0, SkPoint p1, SkScalar distance, unsigned ptIndex);
+    SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,
+                               int mint, int maxt, unsigned ptIndex);
+    SkScalar compute_conic_segs(const SkConic& conic, SkScalar distance,
+                                                         int mint, const SkPoint& minPt,
+                                                         int maxt, const SkPoint& maxPt,
+                                unsigned ptIndex);
+    SkScalar compute_cubic_segs(const SkPoint pts[4], SkScalar distance,
+                                int mint, int maxt, unsigned ptIndex);
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/gfx/skia/skia/include/core/SkCubicMap.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCubicMap_DEFINED
+#define SkCubicMap_DEFINED
+
+#include "SkPoint.h"
+
+/**
+ *  Fast evaluation of a cubic ease-in / ease-out curve. This is defined as a parametric cubic
+ *  curve inside the unit square.
+ *
+ *  pt[0] is implicitly { 0, 0 }
+ *  pt[3] is implicitly { 1, 1 }
+ *  pts[1,2] are inside the unit square
+ */
+class SK_API SkCubicMap {
+public:
+    SkCubicMap(SkPoint p1, SkPoint p2);
+
+    float computeYFromX(float x) const;
+
+    SkPoint computeFromT(float t) const;
+
+private:
+    enum Type {
+        kLine_Type,     // x == y
+        kCubeRoot_Type, // At^3 == x
+        kSolver_Type,   // general monotonic cubic solver
+    };
+
+    SkPoint fCoeff[3];
+    Type    fType;
+};
+
+#endif
+
--- a/gfx/skia/skia/include/core/SkDeferredDisplayListRecorder.h
+++ b/gfx/skia/skia/include/core/SkDeferredDisplayListRecorder.h
@@ -1,33 +1,33 @@
 /*
  * Copyright 2017 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkDeferredDisplayListMaker_DEFINED
-#define SkDeferredDisplayListMaker_DEFINED
+#ifndef SkDeferredDisplayListRecorder_DEFINED
+#define SkDeferredDisplayListRecorder_DEFINED
 
+#include "../private/SkDeferredDisplayList.h"
 #include "SkImageInfo.h"
 #include "SkRefCnt.h"
 #include "SkSurfaceCharacterization.h"
 #include "SkTypes.h"
 
-#include "../private/SkDeferredDisplayList.h"
-
 class GrBackendFormat;
 class GrBackendTexture;
 class GrContext;
-
 class SkCanvas;
 class SkImage;
+class SkPromiseImageTexture;
 class SkSurface;
 struct SkYUVAIndex;
+struct SkYUVASizeInfo;
 
 /*
  * This class is intended to be used as:
  *   Get an SkSurfaceCharacterization representing the intended gpu-backed destination SkSurface
  *   Create one of these (an SkDDLMaker) on the stack
  *   Get the canvas and render into it
  *   Snap off and hold on to an SkDeferredDisplayList
  *   Once your app actually needs the pixels, call SkSurface::draw(SkDeferredDisplayList*)
@@ -42,51 +42,50 @@ public:
     ~SkDeferredDisplayListRecorder();
 
     const SkSurfaceCharacterization& characterization() const {
         return fCharacterization;
     }
 
     // The backing canvas will become invalid (and this entry point will return
     // null) once 'detach' is called.
-    // Note: ownership of the SkCanvas is not transfered via this call.
+    // Note: ownership of the SkCanvas is not transferred via this call.
     SkCanvas* getCanvas();
 
     std::unique_ptr<SkDeferredDisplayList> detach();
 
-    // Matches the defines in SkImage_Gpu.h
-    typedef void* TextureContext;
-    typedef void (*TextureReleaseProc)(TextureContext textureContext);
-    typedef void (*TextureFulfillProc)(TextureContext textureContext, GrBackendTexture* outTexture);
-    typedef void (*PromiseDoneProc)(TextureContext textureContext);
+    using PromiseImageTextureContext = void*;
+    using PromiseImageTextureFulfillProc =
+            sk_sp<SkPromiseImageTexture> (*)(PromiseImageTextureContext);
+    using PromiseImageTextureReleaseProc = void (*)(PromiseImageTextureContext);
+    using PromiseImageTextureDoneProc = void (*)(PromiseImageTextureContext);
 
     /**
         Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The main
         difference is that the client doesn't have the backend texture on the gpu yet but they know
         all the properties of the texture. So instead of passing in a GrBackendTexture the client
         supplies a GrBackendFormat, width, height, and GrMipMapped state.
 
         When we actually send the draw calls to the GPU, we will call the textureFulfillProc and
         the client will return a GrBackendTexture to us. The properties of the GrBackendTexture must
         match those set during the SkImage creation, and it must have a valid backend gpu texture.
         The gpu texture supplied by the client must stay valid until we call the textureReleaseProc.
 
-        When we are done with the texture returned by the textureFulfillProc we will call the
-        textureReleaseProc passing in the textureContext. This is a signal to the client that they
-        are free to delete the underlying gpu texture. If future draws also use the same promise
-        image we will call the textureFulfillProc again if we've already called the
-        textureReleaseProc. We will always call textureFulfillProc and textureReleaseProc in pairs.
-        In other words we will never call textureFulfillProc or textureReleaseProc multiple times
-        for the same textureContext before calling the other.
+        When all the following are true:
+            * the promise image is deleted,
+            * any SkDeferredDisplayLists that recorded draws referencing the image are deleted,
+            * and the texture is safe to delete in the underlying API with respect to drawn
+              SkDeferredDisplayLists that reference the image
+        the textureReleaseProc and then textureDoneProc are called. The texture can be deleted
+        by the client as soon as textureReleaseProc is called. There is at most one call to each of
+        textureFulfillProc, textureReleaseProc, and textureDoneProc. textureDoneProc is always
+        called even if image creation fails or if the image is never fulfilled (e.g. it is never
+        drawn). If textureFulfillProc is called then textureReleaseProc will always be called even
+        if textureFulfillProc fails.
 
-        We call the promiseDoneProc when we will no longer call the textureFulfillProc again. We
-        pass in the textureContext as a parameter to the promiseDoneProc. We also guarantee that
-        there will be no outstanding textureReleaseProcs that still need to be called when we call
-        the textureDoneProc. Thus when the textureDoneProc gets called the client is able to cleanup
-        all GPU objects and meta data needed for the textureFulfill call.
 
         This call is only valid if the SkDeferredDisplayListRecorder is backed by a gpu context.
 
         @param backendFormat       format of promised gpu texture
         @param width               width of promised gpu texture
         @param height              height of promised gpu texture
         @param mipMapped           mip mapped state of promised gpu texture
         @param origin              one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
@@ -106,39 +105,41 @@ public:
     sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat,
                                       int width,
                                       int height,
                                       GrMipMapped mipMapped,
                                       GrSurfaceOrigin origin,
                                       SkColorType colorType,
                                       SkAlphaType alphaType,
                                       sk_sp<SkColorSpace> colorSpace,
-                                      TextureFulfillProc textureFulfillProc,
-                                      TextureReleaseProc textureReleaseProc,
-                                      PromiseDoneProc promiseDoneProc,
-                                      TextureContext textureContext);
+                                      PromiseImageTextureFulfillProc textureFulfillProc,
+                                      PromiseImageTextureReleaseProc textureReleaseProc,
+                                      PromiseImageTextureDoneProc textureDoneProc,
+                                      PromiseImageTextureContext textureContext);
 
     /**
         This entry point operates the same as 'makePromiseTexture' except that its
         textureFulfillProc can be called up to four times to fetch the required YUVA
         planes (passing a different textureContext to each call). So, if the 'yuvaIndices'
         indicate that only the first two backend textures are used, 'textureFulfillProc' will
         be called with the first two 'textureContexts'.
      */
     sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,
                                           const GrBackendFormat yuvaFormats[],
+                                          const SkISize yuvaSizes[],
                                           const SkYUVAIndex yuvaIndices[4],
                                           int imageWidth,
                                           int imageHeight,
                                           GrSurfaceOrigin imageOrigin,
                                           sk_sp<SkColorSpace> imageColorSpace,
-                                          TextureFulfillProc textureFulfillProc,
-                                          TextureReleaseProc textureReleaseProc,
-                                          PromiseDoneProc promiseDoneProc,
-                                          TextureContext textureContexts[]);
+                                          PromiseImageTextureFulfillProc textureFulfillProc,
+                                          PromiseImageTextureReleaseProc textureReleaseProc,
+                                          PromiseImageTextureDoneProc textureDoneProc,
+                                          PromiseImageTextureContext textureContexts[]);
+
 private:
     bool init();
 
     const SkSurfaceCharacterization             fCharacterization;
 
 #if SK_SUPPORT_GPU
     sk_sp<GrContext>                            fContext;
     sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData;
--- a/gfx/skia/skia/include/core/SkDrawable.h
+++ b/gfx/skia/skia/include/core/SkDrawable.h
@@ -4,42 +4,92 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkDrawable_DEFINED
 #define SkDrawable_DEFINED
 
 #include "SkFlattenable.h"
+#include "SkImageInfo.h"
 #include "SkScalar.h"
 
+class GrBackendDrawableInfo;
 class SkCanvas;
 class SkMatrix;
 class SkPicture;
+enum class GrBackendApi : unsigned;
 struct SkRect;
 
 /**
  *  Base-class for objects that draw into SkCanvas.
  *
  *  The object has a generation ID, which is guaranteed to be unique across all drawables. To
  *  allow for clients of the drawable that may want to cache the results, the drawable must
  *  change its generation ID whenever its internal state changes such that it will draw differently.
  */
 class SK_API SkDrawable : public SkFlattenable {
 public:
-    SkDrawable();
-
     /**
      *  Draws into the specified content. The drawing sequence will be balanced upon return
      *  (i.e. the saveLevel() on the canvas will match what it was when draw() was called,
      *  and the current matrix and clip settings will not be changed.
      */
     void draw(SkCanvas*, const SkMatrix* = nullptr);
     void draw(SkCanvas*, SkScalar x, SkScalar y);
 
+    /**
+     *  When using the GPU backend it is possible for a drawable to execute using the underlying 3D
+     *  API rather than the SkCanvas API. It does so by creating a GpuDrawHandler. The GPU backend
+     *  is deferred so the handler will be given access to the 3D API at the correct point in the
+     *  drawing stream as the GPU backend flushes. Since the drawable may mutate, each time it is
+     *  drawn to a GPU-backed canvas a new handler is snapped, representing the drawable's state at
+     *  the time of the snap.
+     *
+     *  When the GPU backend flushes to the 3D API it will call the draw method on the
+     *  GpuDrawHandler. At this time the drawable may add commands to the stream of GPU commands for
+     *  the unerlying 3D API. The draw function takes a GrBackendDrawableInfo which contains
+     *  information about the current state of 3D API which the caller must respect. See
+     *  GrBackendDrawableInfo for more specific details on what information is sent and the
+     *  requirements for different 3D APIs.
+     *
+     *  Additionaly there may be a slight delay from when the drawable adds its commands to when
+     *  those commands are actually submitted to the GPU. Thus the drawable or GpuDrawHandler is
+     *  required to keep any resources that are used by its added commands alive and valid until
+     *  those commands are submitted to the GPU. The GpuDrawHandler will be kept alive and then
+     *  deleted once the commands are submitted to the GPU. The dtor of the GpuDrawHandler is the
+     *  signal to the drawable that the commands have all been submitted. Different 3D APIs may have
+     *  additional requirements for certain resources which require waiting for the GPU to finish
+     *  all work on those resources before reusing or deleting them. In this case, the drawable can
+     *  use the dtor call of the GpuDrawHandler to add a fence to the GPU to track when the GPU work
+     *  has completed.
+     *
+     *  Currently this is only supported for the GPU Vulkan backend.
+     */
+
+    class GpuDrawHandler {
+    public:
+        virtual ~GpuDrawHandler() {}
+
+        virtual void draw(const GrBackendDrawableInfo&) {}
+    };
+
+    /**
+     * Snaps off a GpuDrawHandler to represent the state of the SkDrawable at the time the snap is
+     * called. This is used for executing GPU backend specific draws intermixed with normal Skia GPU
+     * draws. The GPU API, which will be used for the draw, as well as the full matrix, device clip
+     * bounds and imageInfo of the target buffer are passed in as inputs.
+     */
+    std::unique_ptr<GpuDrawHandler> snapGpuDrawHandler(GrBackendApi backendApi,
+                                                       const SkMatrix& matrix,
+                                                       const SkIRect& clipBounds,
+                                                       const SkImageInfo& bufferInfo) {
+        return this->onSnapGpuDrawHandler(backendApi, matrix, clipBounds, bufferInfo);
+    }
+
     SkPicture* newPictureSnapshot();
 
     /**
      *  Return a unique value for this instance. If two calls to this return the same value,
      *  it is presumed that calling the draw() method will render the same thing as well.
      *
      *  Subclasses that change their state should call notifyDrawingChanged() to ensure that
      *  a new value will be returned the next time it is called.
@@ -71,21 +121,35 @@ public:
     static sk_sp<SkDrawable> Deserialize(const void* data, size_t size,
                                           const SkDeserialProcs* procs = nullptr) {
         return sk_sp<SkDrawable>(static_cast<SkDrawable*>(
                                   SkFlattenable::Deserialize(
                                   kSkDrawable_Type, data, size, procs).release()));
     }
 
     Factory getFactory() const override { return nullptr; }
+    const char* getTypeName() const override { return nullptr; }
 
 protected:
+    SkDrawable();
+
     virtual SkRect onGetBounds() = 0;
     virtual void onDraw(SkCanvas*) = 0;
 
+    virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&,
+                                                                 const SkIRect& /*clipBounds*/,
+                                                                 const SkImageInfo&) {
+        return nullptr;
+    }
+
+    // TODO: Delete this once Android gets updated to take the clipBounds version above.
+    virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&) {
+        return nullptr;
+    }
+
     /**
      *  Default implementation calls onDraw() with a canvas that records into a picture. Subclasses
      *  may override if they have a more efficient way to return a picture for the current state
      *  of their drawable. Note: this picture must draw the same as what would be drawn from
      *  onDraw().
      */
     virtual SkPicture* onNewPictureSnapshot();
 
--- a/gfx/skia/skia/include/core/SkExecutor.h
+++ b/gfx/skia/skia/include/core/SkExecutor.h
@@ -5,18 +5,19 @@
  * found in the LICENSE file.
  */
 
 #ifndef SkExecutor_DEFINED
 #define SkExecutor_DEFINED
 
 #include <functional>
 #include <memory>
+#include "SkTypes.h"
 
-class SkExecutor {
+class SK_API SkExecutor {
 public:
     virtual ~SkExecutor();
 
     // Create a thread pool SkExecutor with a fixed thread count, by default the number of cores.
     static std::unique_ptr<SkExecutor> MakeFIFOThreadPool(int threads = 0);
     static std::unique_ptr<SkExecutor> MakeLIFOThreadPool(int threads = 0);
 
     // There is always a default SkExecutor available by calling SkExecutor::GetDefault().
--- a/gfx/skia/skia/include/core/SkFlattenable.h
+++ b/gfx/skia/skia/include/core/SkFlattenable.h
@@ -47,37 +47,23 @@ public:
     /** Implement this to return a factory function pointer that can be called
      to recreate your class given a buffer (previously written to by your
      override of flatten().
      */
     virtual Factory getFactory() const = 0;
 
     /**
      *  Returns the name of the object's class.
-     *
-     *  Subclasses should override this function if they intend to provide
-     *  support for flattening without using the global registry.
-     *
-     *  If the flattenable is registered, there is no need to override.
      */
-    virtual const char* getTypeName() const {
-    #ifdef SK_DISABLE_READBUFFER
-        // Should not be reachable by PathKit WebAssembly Code.
-        SkASSERT(false);
-        return nullptr;
-    #else
-        return FactoryToName(getFactory());
-    #endif
-    }
+    virtual const char* getTypeName() const = 0;
 
     static Factory NameToFactory(const char name[]);
     static const char* FactoryToName(Factory);
-    static bool NameToType(const char name[], Type* type);
 
-    static void Register(const char name[], Factory, Type);
+    static void Register(const char name[], Factory);
 
     /**
      *  Override this if your subclass needs to record data that it will need to recreate itself
      *  from its CreateProc (returned by getFactory()).
      *
      *  DEPRECATED public : will move to protected ... use serialize() instead
      */
     virtual void flatten(SkWriteBuffer&) const {}
@@ -91,23 +77,30 @@ public:
     size_t serialize(void* memory, size_t memory_size,
                      const SkSerialProcs* = nullptr) const;
     static sk_sp<SkFlattenable> Deserialize(Type, const void* data, size_t length,
                                             const SkDeserialProcs* procs = nullptr);
 
 protected:
     class PrivateInitializer {
     public:
-        static void InitCore();
         static void InitEffects();
         static void InitImageFilters();
     };
 
 private:
-    static void InitializeFlattenablesIfNeeded();
+    static void RegisterFlattenablesIfNeeded();
     static void Finalize();
 
     friend class SkGraphics;
 
     typedef SkRefCnt INHERITED;
 };
 
+#define SK_REGISTER_FLATTENABLE(type) SkFlattenable::Register(#type, type::CreateProc)
+
+#define SK_FLATTENABLE_HOOKS(type)                                   \
+    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);           \
+    friend class SkFlattenable::PrivateInitializer;                  \
+    Factory getFactory() const override { return type::CreateProc; } \
+    const char* getTypeName() const override { return #type; }
+
 #endif
--- a/gfx/skia/skia/include/core/SkFont.h
+++ b/gfx/skia/skia/include/core/SkFont.h
@@ -3,162 +3,516 @@
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkFont_DEFINED
 #define SkFont_DEFINED
 
-#include "SkRefCnt.h"
+#include "SkFontTypes.h"
 #include "SkScalar.h"
-
-class SkPaint;
-class SkTypeface;
-
-enum SkTextEncoding {
-    kUTF8_SkTextEncoding,
-    kUTF16_SkTextEncoding,
-    kUTF32_SkTextEncoding,
-    kGlyphID_SkTextEncoding,
-};
-
-/*
- 1. The Hinting enum in SkPaint is gone entirely, absorbed into SkFont's flags.
-
- 2. SkPaint Flags look like this today
+#include "SkTypeface.h"
 
- enum Flags {
-     kAntiAlias_Flag       = 0x01,   //!< mask to enable antialiasing
-     kDither_Flag          = 0x04,   //!< mask to enable dithering
-     kFakeBoldText_Flag    = 0x20,   //!< mask to enable fake-bold text
-     kLinearText_Flag      = 0x40,   //!< mask to enable linear-text
-     kSubpixelText_Flag    = 0x80,   //!< mask to enable subpixel text positioning
-     kLCDRenderText_Flag   = 0x200,  //!< mask to enable subpixel glyph renderering
-     kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes
-     kAutoHinting_Flag     = 0x800,  //!< mask to force Freetype's autohinter
-     kVerticalText_Flag    = 0x1000,
- };
-
- SkFont would absorb these:
-
-     kFakeBoldText_Flag    = 0x20,   //!< mask to enable fake-bold text
-     kLinearText_Flag      = 0x40,   //!< mask to enable linear-text
-     kSubpixelText_Flag    = 0x80,   //!< mask to enable subpixel text positioning
-     kLCDRenderText_Flag   = 0x200,  //!< mask to enable subpixel glyph renderering
-     kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes
-     kAutoHinting_Flag     = 0x800,  //!< mask to force Freetype's autohinter
-     kVerticalText_Flag    = 0x1000,
-
- leaving these still in paint
-
-     kAntiAlias_Flag       = 0x01,   //!< mask to enable antialiasing
-     kDither_Flag          = 0x04,   //!< mask to enable dithering
+class SkMatrix;
+class SkPaint;
+class SkPath;
+struct SkFontMetrics;
 
- 3. Antialiasing
-
-    SkFont has a mask-type: BW, AA, LCD
-    SkPaint has antialias boolean
-
-    What to do if the font's mask-type disagrees with the paint?
-
- */
-
-class SkFont : public SkRefCnt {
+/** \class SkFont
+    SkFont controls options applied when drawing and measuring text.
+*/
+class SK_API SkFont {
 public:
-    enum Flags {
-        /**
-         *  Use the system's automatic hinting mechanism to hint the typeface.
-         *  This is a last resort hinting method applied only if other hinting methods do not apply.
-         *  TODO: where to put auto-normal vs auto-light?
-         */
-        kEnableAutoHints_Flag       = 1 << 0,
-
-        /**
-         *  If the typeface contains explicit bytecodes for hinting, use them.
-         *  If both bytecode and auto hints are specified, attempt to use the bytecodes first;
-         *  if that fails (e.g. there are no codes), then attempt to autohint.
-         */
-        kEnableByteCodeHints_Flag   = 1 << 1,
-
-        /**
-         *  If the typeface contains explicit bitmaps for hinting, use them.
-         *  If both bytecode and auto hints are also specified, attempt to use the bitmaps first;
-         *  if that fails (e.g. there are no bitmaps), then attempt to bytecode or autohint.
-         */
-        kEmbeddedBitmaps_Flag       = 1 << 2,
-
-        /**
-         *  Use rounded metric values (e.g. advance).
-         *  If either auto or bytecode hinting was used, apply those results to the metrics of the
-         *  glyphs as well. If no hinting was applied, the metrics will just be rounded to the
-         *  nearest integer.
-         *
-         *  This applies to calls that return metrics (e.g. measureText) and to drawing the glyphs
-         *  (see SkCanvas drawText and drawPosText).
-         */
-        kUseNonlinearMetrics_Flag   = 1 << 3,
-
-        kVertical_Flag              = 1 << 4,
-
-        kEmbolden_Flag              = 1 << 6,
+    /** Whether edge pixels draw opaque or with partial transparency.
+    */
+    enum class Edging {
+        kAlias,              //!< no transparent pixels on glyph edges
+        kAntiAlias,          //!< may have transparent pixels on glyph edges
+        kSubpixelAntiAlias,  //!< glyph positioned in pixel using transparency
     };
 
-    enum MaskType {
-        kBW_MaskType,
-        kA8_MaskType,
-        kLCD_MaskType,
-    };
+    /** Constructs SkFont with default values.
+
+        @return  default initialized SkFont
+    */
+    SkFont();
+
+    /** Constructs SkFont with default values with SkTypeface and size in points.
+
+        @param typeface  font and style used to draw and measure text
+        @param size      typographic height of text
+        @return          initialized SkFont
+    */
+    SkFont(sk_sp<SkTypeface> typeface, SkScalar size);
+
+    /** Constructs SkFont with default values with SkTypeface.
+
+        @param typeface  font and style used to draw and measure text
+        @return          initialized SkFont
+    */
+    explicit SkFont(sk_sp<SkTypeface> typeface);
+
+
+    /** Constructs SkFont with default values with SkTypeface and size in points,
+        horizontal scale, and horizontal skew. Horizontal scale emulates condensed
+        and expanded fonts. Horizontal skew emulates oblique fonts.
+
+        @param typeface  font and style used to draw and measure text
+        @param size      typographic height of text
+        @param scaleX    text horizontal scale
+        @param skewX     additional shear on x-axis relative to y-axis
+        @return          initialized SkFont
+    */
+    SkFont(sk_sp<SkTypeface> typeface, SkScalar size, SkScalar scaleX, SkScalar skewX);
+
+
+    /** Compares SkFont and font, and returns true if they are equivalent.
+        May return false if SkTypeface has identical contents but different pointers.
+
+        @param font  font to compare
+        @return      true if SkFont pair are equivalent
+    */
+    bool operator==(const SkFont& font) const;
+
+    /** Compares SkFont and font, and returns true if they are not equivalent.
+        May return true if SkTypeface has identical contents but different pointers.
+
+        @param font  font to compare
+        @return      true if SkFont pair are not equivalent
+    */
+    bool operator!=(const SkFont& font) const { return !(*this == font); }
+
+    /** If true, instructs the font manager to always hint glyphs.
+        Returned value is only meaningful if platform uses FreeType as the font manager.
+
+        @return  true if all glyphs are hinted
+    */
+    bool isForceAutoHinting() const { return SkToBool(fFlags & kForceAutoHinting_PrivFlag); }
+
+    /** Returns true if font engine may return glyphs from font bitmaps instead of from outlines.
+
+        @return  true if glyphs may be font bitmaps
+    */
+    bool isEmbeddedBitmaps() const { return SkToBool(fFlags & kEmbeddedBitmaps_PrivFlag); }
+
+    /** Returns true if glyphs at different sub-pixel positions may differ on pixel edge coverage.
+
+        @return  true if glyph positioned in pixel using transparency
+    */
+    bool isSubpixel() const { return SkToBool(fFlags & kSubpixel_PrivFlag); }
 
-    static sk_sp<SkFont> Make(sk_sp<SkTypeface>, SkScalar size, MaskType, uint32_t flags);
-    static sk_sp<SkFont> Make(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX,
-                              MaskType, uint32_t flags);
+    /** Returns true if text is converted to SkPath before drawing and measuring.
+
+        @return  true glyph hints are never applied
+    */
+    bool isLinearMetrics() const { return SkToBool(fFlags & kLinearMetrics_PrivFlag); }
+
+    /** Returns true if bold is approximated by increasing the stroke width when creating glyph
+        bitmaps from outlines.
+
+        @return  bold is approximated through stroke width
+    */
+    bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_PrivFlag); }
+
+    /** Sets whether to always hint glyphs.
+        If forceAutoHinting is set, instructs the font manager to always hint glyphs.
+
+        Only affects platforms that use FreeType as the font manager.
+
+        @param forceAutoHinting  setting to always hint glyphs
+    */
+    void setForceAutoHinting(bool forceAutoHinting);
+
+    /** Requests, but does not require, to use bitmaps in fonts instead of outlines.
+
+        @param embeddedBitmaps  setting to use bitmaps in fonts
+    */
+    void setEmbeddedBitmaps(bool embeddedBitmaps);
+
+    /** Requests, but does not require, that glyphs respect sub-pixel positioning.
+
+        @param subpixel  setting for sub-pixel positioning
+    */
+    void setSubpixel(bool subpixel);
 
-    /**
-     *  Return a font with the same attributes of this font, but with the specified size.
-     *  If size is not supported (e.g. <= 0 or non-finite) NULL will be returned.
+    /** Requests, but does not require, that glyphs are converted to SkPath
+        before drawing and measuring.
+
+        @param linearMetrics  setting for converting glyphs to paths
+    */
+    void setLinearMetrics(bool linearMetrics);
+
+    /** Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
+
+        @param embolden  setting for bold approximation
+    */
+    void setEmbolden(bool embolden);
+
+    /** Whether edge pixels draw opaque or with partial transparency.
+
+        @return  one of: Edging::kAlias, Edging::kAntiAlias, Edging::kSubpixelAntiAlias
+    */
+    Edging getEdging() const { return (Edging)fEdging; }
+
+    /** Requests, but does not require, that edge pixels draw opaque or with
+        partial transparency.
+
+        @param edging  one of: Edging::kAlias, Edging::kAntiAlias, Edging::kSubpixelAntiAlias
+    */
+    void setEdging(Edging edging);
+
+    /** Sets level of glyph outline adjustment.
+        Does not check for valid values of hintingLevel.
+
+        @param hintingLevel  one of: SkFontHinting::kNone, SkFontHinting::kSlight,
+                                     SkFontHinting::kNormal, SkFontHinting::kFull
+    */
+    void setHinting(SkFontHinting hintingLevel);
+
+    /** Returns level of glyph outline adjustment.
+
+        @return  one of: SkFontHinting::kNone, SkFontHinting::kSlight, SkFontHinting::kNormal,
+                         SkFontHinting::kFull
      */
-    sk_sp<SkFont> makeWithSize(SkScalar size) const;
-    /**
-     *  Return a font with the same attributes of this font, but with the flags.
+    SkFontHinting getHinting() const { return (SkFontHinting)fHinting; }
+
+    /** Returns a font with the same attributes of this font, but with the specified size.
+        Returns nullptr if size is less than zero, infinite, or NaN.
+
+        @param size  typographic height of text
+        @return      initialized SkFont
      */
-    sk_sp<SkFont> makeWithFlags(uint32_t newFlags) const;
+    SkFont makeWithSize(SkScalar size) const;
+
+    /** Returns SkTypeface if set, or nullptr.
+        Does not alter SkTypeface SkRefCnt.
+
+        @return  SkTypeface if previously set, nullptr otherwise
+    */
+    SkTypeface* getTypeface() const {return fTypeface.get(); }
+
+    /** Returns SkTypeface if set, or the default typeface.
+        Does not alter SkTypeface SkRefCnt.
+
+        @return  SkTypeface if previously set or, a pointer to the default typeface if not
+        previously set.
+    */
+    SkTypeface* getTypefaceOrDefault() const;
 
-    SkTypeface* getTypeface() const { return fTypeface.get(); }
+    /** Returns text size in points.
+
+        @return  typographic height of text
+    */
     SkScalar    getSize() const { return fSize; }
+
+    /** Returns text scale on x-axis.
+        Default value is 1.
+
+        @return  text horizontal scale
+    */
     SkScalar    getScaleX() const { return fScaleX; }
+
+    /** Returns text skew on x-axis.
+        Default value is zero.
+
+        @return  additional shear on x-axis relative to y-axis
+    */
     SkScalar    getSkewX() const { return fSkewX; }
-    uint32_t    getFlags() const { return fFlags; }
-    MaskType    getMaskType() const { return (MaskType)fMaskType; }
+
+    /** Increases SkTypeface SkRefCnt by one.
+
+        @return  SkTypeface if previously set, nullptr otherwise
+    */
+    sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
+
+    /** Increases SkTypeface SkRefCnt by one.
+
+        @return  SkTypeface if previously set or, a pointer to the default typeface if not
+        previously set.
+    */
+    sk_sp<SkTypeface> refTypefaceOrDefault() const;
+
+    /** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
+        Pass nullptr to clear SkTypeface and use the default typeface. Increments
+        tf SkRefCnt by one.
+
+        @param tf  font and style used to draw text
+    */
+    void setTypeface(sk_sp<SkTypeface> tf) { fTypeface = tf; }
+
+    /** Sets text size in points.
+        Has no effect if textSize is not greater than or equal to zero.
+
+        @param textSize  typographic height of text
+    */
+    void setSize(SkScalar textSize);
+
+    /** Sets text scale on x-axis.
+        Default value is 1.
+
+        @param scaleX  text horizontal scale
+    */
+    void setScaleX(SkScalar scaleX);
 
-    bool isVertical() const { return SkToBool(fFlags & kVertical_Flag); }
-    bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_Flag); }
-    bool isEnableAutoHints() const { return SkToBool(fFlags & kEnableAutoHints_Flag); }
-    bool isEnableByteCodeHints() const { return SkToBool(fFlags & kEnableByteCodeHints_Flag); }
-    bool isUseNonLinearMetrics() const { return SkToBool(fFlags & kUseNonlinearMetrics_Flag); }
+    /** Sets text skew on x-axis.
+        Default value is zero.
+
+        @param skewX  additional shear on x-axis relative to y-axis
+    */
+    void setSkewX(SkScalar skewX);
+
+    /** Converts text into glyph indices.
+        Returns the number of glyph indices represented by text.
+        SkTextEncoding specifies how text represents characters or glyphs.
+        glyphs may be nullptr, to compute the glyph count.
+
+        Does not check text for valid character codes or valid glyph indices.
+
+        If byteLength equals zero, returns zero.
+        If byteLength includes a partial character, the partial character is ignored.
 
-    int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding,
+        If encoding is kUTF8_SkTextEncoding and text contains an invalid UTF-8 sequence,
+        zero is returned.
+
+        When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
+        SkTextEncoding::kUTF32; then each Unicode codepoint is mapped to a
+        single glyph.  This function uses the default character-to-glyph
+        mapping from the SkTypeface and maps characters not found in the
+        SkTypeface to zero.
+
+        If maxGlyphCount is not sufficient to store all the glyphs, no glyphs are copied.
+        The total glyph count is returned for subsequent buffer reallocation.
+
+        @param text          character storage encoded with SkTextEncoding
+        @param byteLength    length of character storage in bytes
+        @param encoding      one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
+                             kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
+        @param glyphs        storage for glyph indices; may be nullptr
+        @param maxGlyphCount storage capacity
+        @return              number of glyphs represented by text of length byteLength
+    */
+    int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
                      SkGlyphID glyphs[], int maxGlyphCount) const;
 
-    int countText(const void* text, size_t byteLength, SkTextEncoding encoding) {
+    /** Returns glyph index for Unicode character.
+
+        If the character is not supported by the SkTypeface, returns 0.
+
+        @param uni  Unicode character
+        @return     glyph index
+    */
+    SkGlyphID unicharToGlyph(SkUnichar uni) const;
+
+    /** Returns number of glyphs represented by text.
+
+        If encoding is kUTF8_SkTextEncoding, kUTF16_SkTextEncoding, or
+        kUTF32_SkTextEncoding; then each Unicode codepoint is mapped to a
+        single glyph.
+
+        @param text          character storage encoded with SkTextEncoding
+        @param byteLength    length of character storage in bytes
+        @param encoding      one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
+                             kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
+        @return              number of glyphs represented by text of length byteLength
+    */
+    int countText(const void* text, size_t byteLength, SkTextEncoding encoding) const {
         return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);
     }
 
-    SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding) const;
+    /** Returns the advance width of text.
+        The advance is the normal distance to move before drawing additional text.
+        Returns the bounding box of text if bounds is not nullptr.
+
+        @param text        character storage encoded with SkTextEncoding
+        @param byteLength  length of character storage in bytes
+        @param encoding    one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
+                           kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
+        @param bounds      returns bounding box relative to (0, 0) if not nullptr
+        @return            number of glyphs represented by text of length byteLength
+    */
+    SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
+                         SkRect* bounds = nullptr) const {
+        return this->measureText(text, byteLength, encoding, bounds, nullptr);
+    }
+
+    /** Returns the advance width of text.
+        The advance is the normal distance to move before drawing additional text.
+        Returns the bounding box of text if bounds is not nullptr. paint
+        stroke width or SkPathEffect may modify the advance with.
+
+        @param text        character storage encoded with SkTextEncoding
+        @param byteLength  length of character storage in bytes
+        @param encoding    one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
+                           kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
+        @param bounds      returns bounding box relative to (0, 0) if not nullptr
+        @param paint       optional; may be nullptr
+        @return            number of glyphs represented by text of length byteLength
+    */
+    SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
+                         SkRect* bounds, const SkPaint* paint) const;
+
+    /** DEPRECATED
+        Retrieves the advance and bounds for each glyph in glyphs.
+        Both widths and bounds may be nullptr.
+        If widths is not nullptr, widths must be an array of count entries.
+        if bounds is not nullptr, bounds must be an array of count entries.
+
+        @param glyphs      array of glyph indices to be measured
+        @param count       number of glyphs
+        @param widths      returns text advances for each glyph; may be nullptr
+        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
+    */
+    void getWidths(const uint16_t glyphs[], int count, SkScalar widths[], SkRect bounds[]) const {
+        this->getWidthsBounds(glyphs, count, widths, bounds, nullptr);
+    }
+
+    // DEPRECATED
+    void getWidths(const uint16_t glyphs[], int count, SkScalar widths[], std::nullptr_t) const {
+        this->getWidths(glyphs, count, widths);
+    }
+
+    /** Retrieves the advance and bounds for each glyph in glyphs.
+        Both widths and bounds may be nullptr.
+        If widths is not nullptr, widths must be an array of count entries.
+        if bounds is not nullptr, bounds must be an array of count entries.
+
+        @param glyphs      array of glyph indices to be measured
+        @param count       number of glyphs
+        @param widths      returns text advances for each glyph
+     */
+    void getWidths(const uint16_t glyphs[], int count, SkScalar widths[]) const {
+        this->getWidthsBounds(glyphs, count, widths, nullptr, nullptr);
+    }
+
+    /** Retrieves the advance and bounds for each glyph in glyphs.
+        Both widths and bounds may be nullptr.
+        If widths is not nullptr, widths must be an array of count entries.
+        if bounds is not nullptr, bounds must be an array of count entries.
+
+        @param glyphs      array of glyph indices to be measured
+        @param count       number of glyphs
+        @param widths      returns text advances for each glyph; may be nullptr
+        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
+        @param paint       optional, specifies stroking, SkPathEffect and SkMaskFilter
+     */
+    void getWidthsBounds(const uint16_t glyphs[], int count, SkScalar widths[], SkRect bounds[],
+                         const SkPaint* paint) const;
+
 
-    static sk_sp<SkFont> Testing_CreateFromPaint(const SkPaint&);
+    /** Retrieves the bounds for each glyph in glyphs.
+        bounds must be an array of count entries.
+        If paint is not nullptr, its stroking, SkPathEffect, and SkMaskFilter fields are respected.
+
+        @param glyphs      array of glyph indices to be measured
+        @param count       number of glyphs
+        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
+        @param paint       optional, specifies stroking, SkPathEffect, and SkMaskFilter
+     */
+    void getBounds(const uint16_t glyphs[], int count, SkRect bounds[],
+                   const SkPaint* paint) const {
+        this->getWidthsBounds(glyphs, count, nullptr, bounds, paint);
+    }
+
+    /** Retrieves the positions for each glyph, beginning at the specified origin. The caller
+        must allocated at least count number of elements in the pos[] array.
+
+        @param glyphs   array of glyph indices to be positioned
+        @param count    number of glyphs
+        @param pos      returns glyphs positions
+        @param origin   location of the first glyph. Defaults to {0, 0}.
+     */
+    void getPos(const uint16_t glyphs[], int count, SkPoint pos[], SkPoint origin = {0, 0}) const;
+
+    /** Retrieves the x-positions for each glyph, beginning at the specified origin. The caller
+        must allocated at least count number of elements in the xpos[] array.
+
+        @param glyphs   array of glyph indices to be positioned
+        @param count    number of glyphs
+        @param xpos     returns glyphs x-positions
+        @param origin   x-position of the first glyph. Defaults to 0.
+     */
+    void getXPos(const uint16_t glyphs[], int count, SkScalar xpos[], SkScalar origin = 0) const;
+
+    /** Returns path corresponding to glyph outline.
+        If glyph has an outline, copies outline to path and returns true.
+        path returned may be empty.
+        If glyph is described by a bitmap, returns false and ignores path parameter.
+
+        @param glyphID  index of glyph
+        @param path     pointer to existing SkPath
+        @return         true if glyphID is described by path
+     */
+    bool getPath(uint16_t glyphID, SkPath* path) const;
+
+    /** Returns path corresponding to glyph array.
+
+        @param glyphIDs      array of glyph indices
+        @param count         number of glyphs
+        @param glyphPathProc function returning one glyph description as path
+        @param ctx           function context
+   */
+    void getPaths(const uint16_t glyphIDs[], int count,
+                  void (*glyphPathProc)(const SkPath* pathOrNull, const SkMatrix& mx, void* ctx),
+                  void* ctx) const;
+
+    /** Returns SkFontMetrics associated with SkTypeface.
+        The return value is the recommended spacing between lines: the sum of metrics
+        descent, ascent, and leading.
+        If metrics is not nullptr, SkFontMetrics is copied to metrics.
+        Results are scaled by text size but does not take into account
+        dimensions required by text scale, text skew, fake bold,
+        style stroke, and SkPathEffect.
+
+        @param metrics  storage for SkFontMetrics; may be nullptr
+        @return         recommended spacing between lines
+    */
+    SkScalar getMetrics(SkFontMetrics* metrics) const;
+
+    /** Returns the recommended spacing between lines: the sum of metrics
+        descent, ascent, and leading.
+        Result is scaled by text size but does not take into account
+        dimensions required by stroking and SkPathEffect.
+        Returns the same result as getMetrics().
+
+        @return  recommended spacing between lines
+    */
+    SkScalar getSpacing() const { return this->getMetrics(nullptr); }
+
+    /** Experimental.
+     *  Dumps fields of the font to SkDebugf. May change its output over time, so clients should
+     *  not rely on this for anything specific. Used to aid in debugging.
+     */
+    void dump() const;
 
 private:
-    static constexpr int kAllFlags = 0xFF;
+    enum PrivFlags {
+        kForceAutoHinting_PrivFlag      = 1 << 0,
+        kEmbeddedBitmaps_PrivFlag       = 1 << 1,
+        kSubpixel_PrivFlag              = 1 << 2,
+        kLinearMetrics_PrivFlag         = 1 << 3,
+        kEmbolden_PrivFlag              = 1 << 4,
+    };
 
-    SkFont(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType,
-           uint32_t flags);
+    static constexpr unsigned kAllFlags = 0x1F;
 
     sk_sp<SkTypeface> fTypeface;
     SkScalar    fSize;
     SkScalar    fScaleX;
     SkScalar    fSkewX;
-    uint16_t    fFlags;
-    uint8_t     fMaskType;
-//  uint8_t     fPad;
+    uint8_t     fFlags;
+    uint8_t     fEdging;
+    uint8_t     fHinting;
+
+    SkScalar setupForAsPaths(SkPaint*);
+    bool hasSomeAntiAliasing() const;
+
+    void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;
+
+    friend class GrTextBlob;
+    friend class SkCanonicalizeFont;
+    friend class SkFontPriv;
+    friend class SkGlyphRunListPainter;
+    friend class SkTextBlobCacheDiffCanvas;
+    friend class SVGTextBuilder;
 };
 
 #endif
new file mode 100644
--- /dev/null
+++ b/gfx/skia/skia/include/core/SkFontMetrics.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMetrics_DEFINED
+#define SkFontMetrics_DEFINED
+
+#include "SkScalar.h"
+
+struct SK_API SkFontMetrics {
+
+    /** \enum FontMetricsFlags
+     FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
+     the underline or strikeout metric may be valid and zero.
+     Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
+     */
+    enum FontMetricsFlags {
+        kUnderlineThicknessIsValid_Flag = 1 << 0, //!< set if fUnderlineThickness is valid
+        kUnderlinePositionIsValid_Flag  = 1 << 1, //!< set if fUnderlinePosition is valid
+        kStrikeoutThicknessIsValid_Flag = 1 << 2, //!< set if fStrikeoutThickness is valid
+        kStrikeoutPositionIsValid_Flag  = 1 << 3, //!< set if fStrikeoutPosition is valid
+    };
+
+    uint32_t fFlags;              //!< is set to FontMetricsFlags when metrics are valid
+    SkScalar fTop;                //!< extent above baseline
+    SkScalar fAscent;             //!< distance to reserve above baseline
+    SkScalar fDescent;            //!< distance to reserve below baseline
+    SkScalar fBottom;             //!< extent below baseline
+    SkScalar fLeading;            //!< distance to add between lines
+    SkScalar fAvgCharWidth;       //!< average character width
+    SkScalar fMaxCharWidth;       //!< maximum character width
+    SkScalar fXMin;               //!< minimum x
+    SkScalar fXMax;               //!< maximum x
+    SkScalar fXHeight;            //!< height of lower-case 'x'
+    SkScalar fCapHeight;          //!< height of an upper-case letter
+    SkScalar fUnderlineThickness; //!< underline thickness
+    SkScalar fUnderlinePosition;  //!< underline position relative to baseline
+    SkScalar fStrikeoutThickness; //!< strikeout thickness
+    SkScalar fStrikeoutPosition;  //!< strikeout position relative to baseline
+
+    /** Returns true if SkFontMetrics has a valid underline thickness, and sets
+     thickness to that value. If the underline thickness is not valid,
+     return false, and ignore thickness.
+
+     @param thickness  storage for underline width
+     @return           true if font specifies underline width
+     */
+    bool hasUnderlineThickness(SkScalar* thickness) const {
+        if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {
+            *thickness = fUnderlineThickness;
+            return true;
+        }
+        return false;
+    }
+
+    /** Returns true if SkFontMetrics has a valid underline position, and sets
+     position to that value. If the underline position is not valid,
+     return false, and ignore position.
+
+     @param position  storage for underline position
+     @return          true if font specifies underline position
+     */
+    bool hasUnderlinePosition(SkScalar* position) const {
+        if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
+            *position = fUnderlinePosition;
+            return true;
+        }
+        return false;
+    }
+
+    /** Returns true if SkFontMetrics has a valid strikeout thickness, and sets
+     thickness to that value. If the underline thickness is not valid,
+     return false, and ignore thickness.
+
+     @param thickness  storage for strikeout width
+     @return           true if font specifies strikeout width
+     */
+    bool hasStrikeoutThickness(SkScalar* thickness) const {
+        if (SkToBool(fFlags & kStrikeoutThicknessIsValid_Flag)) {
+            *thickness = fStrikeoutThickness;
+            return true;
+        }
+        return false;
+    }
+
+    /** Returns true if SkFontMetrics has a valid strikeout position, and sets
+     position to that value. If the underline position is not valid,
+     return false, and ignore position.
+
+     @param position  storage for strikeout position
+     @return          true if font specifies strikeout position
+     */
+    bool hasStrikeoutPosition(SkScalar* position) const {
+        if (SkToBool(fFlags & kStrikeoutPositionIsValid_Flag)) {
+            *position = fStrikeoutPosition;
+            return true;
+        }
+        return false;
+    }
+
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/gfx/skia/skia/include/core/SkFontTypes.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontTypes_DEFINED
+#define SkFontTypes_DEFINED
+
+#include "SkTypes.h"
+// remove me once google3 uses IWYU
+#include "SkTypeface.h"
+
+enum class SkTextEncoding {
+    kUTF8,      //!< uses bytes to represent UTF-8 or ASCII
+    kUTF16,     //!< uses two byte words to represent most of Unicode
+    kUTF32,     //!< uses four byte words to represent all of Unicode
+    kGlyphID,   //!< uses two byte words to represent glyph indices
+};
+
+#define kUTF8_SkTextEncoding    SkTextEncoding::kUTF8
+#define kUTF16_SkTextEncoding   SkTextEncoding::kUTF16
+#define kUTF32_SkTextEncoding   SkTextEncoding::kUTF32
+#define kGlyphID_SkTextEncoding SkTextEncoding::kGlyphID
+
+enum class SkFontHinting {
+    kNone,      //!< glyph outlines unchanged
+    kSlight,    //!< minimal modification to improve constrast
+    kNormal,    //!< glyph outlines modified to improve constrast
+    kFull,      //!< modifies glyph outlines for maximum constrast
+};
+
+#define kNo_SkFontHinting       SkFontHinting::kNone
+#define kSlight_SkFontHinting   SkFontHinting::kSlight
+#define kNormal_SkFontHinting   SkFontHinting::kNormal
+#define kFull_SkFontHinting     SkFontHinting::kFull
+
+#endif
--- a/gfx/skia/skia/include/core/SkICC.h
+++ b/gfx/skia/skia/include/core/SkICC.h
@@ -4,35 +4,16 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkICC_DEFINED
 #define SkICC_DEFINED
 
 #include "SkData.h"
-#include "SkMatrix44.h"
-#include "SkRefCnt.h"
-
-struct SkColorSpaceTransferFn;
-
-SK_API sk_sp<SkData> SkWriteICCProfile(const SkColorSpaceTransferFn&, const float toXYZD50[9]);
 
-namespace SkICC {
-    static inline sk_sp<SkData> WriteToICC(const SkColorSpaceTransferFn& fn,
-                                           const SkMatrix44& toXYZD50) {
-        if (toXYZD50.get(3,0) == 0 && toXYZD50.get(3,1) == 0 && toXYZD50.get(3,2) == 0 &&
-            toXYZD50.get(3,3) == 1 &&
-            toXYZD50.get(0,3) == 0 && toXYZD50.get(1,3) == 0 && toXYZD50.get(2,3) == 0) {
+struct skcms_Matrix3x3;
+struct skcms_TransferFunction;
 
-            float m33[9];
-            for (int r = 0; r < 3; r++)
-            for (int c = 0; c < 3; c++) {
-                m33[3*r+c] = toXYZD50.get(r,c);
-            }
-            return SkWriteICCProfile(fn, m33);
-
-        }
-        return nullptr;
-    }
-}
+SK_API sk_sp<SkData> SkWriteICCProfile(const skcms_TransferFunction&,
+                                       const skcms_Matrix3x3& toXYZD50);
 
 #endif//SkICC_DEFINED
--- a/gfx/skia/skia/include/core/SkImage.h
+++ b/gfx/skia/skia/include/core/SkImage.h
@@ -140,64 +140,86 @@ public:
         row bytes are large enough to hold one row of pixels;
         pixel address is not nullptr.
 
         @param bitmap  SkImageInfo, row bytes, and pixels
         @return        created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromBitmap(const SkBitmap& bitmap);
 
-    /** Creates SkImage from data returned by imageGenerator. Generated data is owned by SkImage and may not
-        be shared or accessed.
+    /** Creates SkImage from data returned by imageGenerator. Generated data is owned by SkImage and
+        may not be shared or accessed.
 
-        subset allows selecting a portion of the full image. Pass nullptr to select the entire image;
-        otherwise, subset must be contained by image bounds.
+        subset allows selecting a portion of the full image. Pass nullptr to select the entire
+        image; otherwise, subset must be contained by image bounds.
 
         SkImage is returned if generator data is valid. Valid data parameters vary by type of data
         and platform.
 
         imageGenerator may wrap SkPicture data, codec data, or custom data.
 
         @param imageGenerator  stock or custom routines to retrieve SkImage
         @param subset          bounds of returned SkImage; may be nullptr
         @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator,
                                             const SkIRect* subset = nullptr);
 
     /** Creates SkImage from encoded data.
-        subset allows selecting a portion of the full image. Pass nullptr to select the entire image;
-        otherwise, subset must be contained by image bounds.
+        subset allows selecting a portion of the full image. Pass nullptr to select the entire
+        image; otherwise, subset must be contained by image bounds.
 
         SkImage is returned if format of the encoded data is recognized and supported.
         Recognized formats vary by platform.
 
         @param encoded  data of SkImage to decode
         @param subset   bounds of returned SkImage; may be nullptr
         @return         created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr);
 
+    // Experimental
+    enum CompressionType {
+        kETC1_CompressionType,
+        kLast_CompressionType = kETC1_CompressionType,
+    };
+
+    /** Creates a GPU-backed SkImage from compressed data.
+
+        SkImage is returned if format of the compressed data is supported.
+        Supported formats vary by platform.
+
+        @param context  GPU context
+        @param data     compressed data to store in SkImage
+        @param width    width of full SkImage
+        @param height   height of full SkImage
+        @param type     type of compression used
+        @return         created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
+                                             int width, int height, CompressionType type);
+
     /** User function called when supplied texture may be deleted.
     */
     typedef void (*TextureReleaseProc)(ReleaseContext releaseContext);
 
     /** Creates SkImage from GPU texture associated with context. Caller is responsible for
         managing the lifetime of GPU texture.
 
         SkImage is returned if format of backendTexture is recognized and supported.
         Recognized formats vary by GPU back-end.
 
         @param context         GPU context
         @param backendTexture  texture residing on GPU
         @param origin          one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
         @param colorType       one of:
                                kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
-                               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
-                               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+                               kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
+                               kRGB_888x_SkColorType, kBGRA_8888_SkColorType,
+                               kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
                                kGray_8_SkColorType, kRGBA_F16_SkColorType
         @param alphaType       one of:
                                kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
                                kUnpremul_SkAlphaType
         @param colorSpace      range of colors; may be nullptr
         @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromTexture(GrContext* context,
@@ -216,20 +238,22 @@ public:
 
         SkImage is returned if format of backendTexture is recognized and supported.
         Recognized formats vary by GPU back-end.
 
         @param context             GPU context
         @param backendTexture      texture residing on GPU
         @param origin              one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
         @param colorType           one of:
-                                   kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
-                                   kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
-                                   kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
-                                   kGray_8_SkColorType, kRGBA_F16_SkColorType
+                                   kUnknown_SkColorType, kAlpha_8_SkColorType,
+                                   kRGB_565_SkColorType, kARGB_4444_SkColorType,
+                                   kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+                                   kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType,
+                                   kRGB_101010x_SkColorType, kGray_8_SkColorType,
+                                   kRGBA_F16_SkColorType
         @param alphaType           one of:
                                    kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
                                    kUnpremul_SkAlphaType
         @param colorSpace          range of colors; may be nullptr
         @param textureReleaseProc  function called when texture can be released
         @param releaseContext      state passed to textureReleaseProc
         @return                    created SkImage, or nullptr
     */
@@ -305,20 +329,22 @@ public:
 
         SkImage is returned if format of backendTexture is recognized and supported.
         Recognized formats vary by GPU back-end.
 
         @param context         GPU context
         @param backendTexture  texture residing on GPU
         @param surfaceOrigin   one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
         @param colorType       one of:
-                               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
-                               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
-                               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
-                               kGray_8_SkColorType, kRGBA_F16_SkColorType
+                               kUnknown_SkColorType, kAlpha_8_SkColorType,
+                               kRGB_565_SkColorType, kARGB_4444_SkColorType,
+                               kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+                               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType,
+                               kRGB_101010x_SkColorType, kGray_8_SkColorType,
+                               kRGBA_F16_SkColorType
         @param alphaType       one of:
                                kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
                                kUnpremul_SkAlphaType
         @param colorSpace      range of colors; may be nullptr
         @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromAdoptedTexture(GrContext* context,
                                                  const GrBackendTexture& backendTexture,
@@ -329,20 +355,20 @@ public:
 
     /** Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA
         image.
 
         @param context         GPU context
         @param yuvColorSpace   How the YUV values are converted to RGB. One of:
                                            kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
                                            kRec709_SkYUVColorSpace
-        @param yuvTextures     array of (up to four) YUVA textures on GPU which contain the,
+        @param yuvaTextures    array of (up to four) YUVA textures on GPU which contain the,
                                possibly interleaved, YUVA planes
-        @param yuvaIndices     array indicating which texture (in 'yuvaTextures') and channel
-                               (in the specified texture) maps to each of Y, U, V, and A.
+        @param yuvaIndices     array indicating which texture in yuvaTextures, and channel
+                               in that texture, maps to each component of YUVA.
         @param imageSize       size of the resulting image
         @param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
                                kTopLeft_GrSurfaceOrigin
         @param imageColorSpace range of colors of the resulting image; may be nullptr
         @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromYUVATexturesCopy(GrContext* context,
                                                    SkYUVColorSpace yuvColorSpace,
@@ -354,20 +380,20 @@ public:
 
     /** Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA
         image. 'backendTexture' is used to store the result of the flattening.
 
         @param context         GPU context
         @param yuvColorSpace   How the YUV values are converted to RGB. One of:
                                            kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
                                            kRec709_SkYUVColorSpace
-        @param yuvTextures     array of (up to four) YUVA textures on GPU which contain the,
+        @param yuvaTextures    array of (up to four) YUVA textures on GPU which contain the,
                                possibly interleaved, YUVA planes
-        @param yuvaIndices     array indicating which texture (in 'yuvaTextures') and channel
-                               (in the specified texture) maps to each of Y, U, V, and A.
+        @param yuvaIndices     array indicating which texture in yuvaTextures, and channel
+                               in that texture, maps to each component of YUVA.
         @param imageSize       size of the resulting image
         @param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
                                kTopLeft_GrSurfaceOrigin
         @param backendTexture  the resource that stores the final pixels
         @param imageColorSpace range of colors of the resulting image; may be nullptr
         @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromYUVATexturesCopyWithExternalBackend(
@@ -375,46 +401,81 @@ public:
             SkYUVColorSpace yuvColorSpace,
             const GrBackendTexture yuvaTextures[],
             const SkYUVAIndex yuvaIndices[4],
             SkISize imageSize,
             GrSurfaceOrigin imageOrigin,
             const GrBackendTexture& backendTexture,
             sk_sp<SkColorSpace> imageColorSpace = nullptr);
 
-    /** Creates SkImage from copy of yuvTextures, an array of textures on GPU.
-        yuvTextures contain pixels for YUV planes of SkImage. Returned SkImage has the dimensions
-        yuvTextures[0]. yuvColorSpace describes how YUV colors convert to RGB colors.
+    /** Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
+        via multitexturing.
 
         @param context         GPU context
-        @param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
-                               kRec709_SkYUVColorSpace
-        @param yuvTextures     array of YUV textures on GPU
-        @param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
-        @param imageColorSpace range of colors; may be nullptr
+        @param yuvColorSpace   How the YUV values are converted to RGB. One of:
+                                           kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                           kRec709_SkYUVColorSpace
+        @param yuvaTextures    array of (up to four) YUVA textures on GPU which contain the,
+                               possibly interleaved, YUVA planes
+        @param yuvaIndices     array indicating which texture in yuvaTextures, and channel
+                               in that texture, maps to each component of YUVA.
+        @param imageSize       size of the resulting image
+        @param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
+                               kTopLeft_GrSurfaceOrigin
+        @param imageColorSpace range of colors of the resulting image; may be nullptr
         @return                created SkImage, or nullptr
     */
+    static sk_sp<SkImage> MakeFromYUVATextures(GrContext* context,
+                                               SkYUVColorSpace yuvColorSpace,
+                                               const GrBackendTexture yuvaTextures[],
+                                               const SkYUVAIndex yuvaIndices[4],
+                                               SkISize imageSize,
+                                               GrSurfaceOrigin imageOrigin,
+                                               sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** Creates SkImage from pixmap array representing YUVA data.
+        SkImage is uploaded to GPU back-end using context.
+
+        Each GrBackendTexture created from yuvaPixmaps array is uploaded to match SkSurface
+        using SkColorSpace of SkPixmap. SkColorSpace of SkImage is determined by imageColorSpace.
+
+        SkImage is returned referring to GPU back-end if context is not nullptr and
+        format of data is recognized and supported. Otherwise, nullptr is returned.
+        Recognized GPU formats vary by platform and GPU back-end.
+
+        @param context                GPU context
+        @param yuvColorSpace          How the YUV values are converted to RGB. One of:
+                                            kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                            kRec709_SkYUVColorSpace
+        @param yuvaPixmaps            array of (up to four) SkPixmap which contain the,
+                                      possibly interleaved, YUVA planes
+        @param yuvaIndices            array indicating which pixmap in yuvaPixmaps, and channel
+                                      in that pixmap, maps to each component of YUVA.
+        @param imageSize              size of the resulting image
+        @param imageOrigin            origin of the resulting image. One of:
+                                            kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param buildMips              create internal YUVA textures as mip map if true
+        @param limitToMaxTextureSize  downscale image to GPU maximum texture size, if necessary
+        @param imageColorSpace        range of colors of the resulting image; may be nullptr
+        @return                       created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromYUVAPixmaps(
+            GrContext* context, SkYUVColorSpace yuvColorSpace, const SkPixmap yuvaPixmaps[],
+            const SkYUVAIndex yuvaIndices[4], SkISize imageSize, GrSurfaceOrigin imageOrigin,
+            bool buildMips, bool limitToMaxTextureSize = false,
+            sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** To be deprecated.
+    */
     static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext* context, SkYUVColorSpace yuvColorSpace,
                                                   const GrBackendTexture yuvTextures[3],
                                                   GrSurfaceOrigin imageOrigin,
                                                   sk_sp<SkColorSpace> imageColorSpace = nullptr);
 
-    /** Creates SkImage from copy of yuvTextures, an array of textures on GPU.
-        yuvTextures contain pixels for YUV planes of SkImage. Returned SkImage has the dimensions
-        yuvTextures[0] and stores pixels in backendTexture. yuvColorSpace describes how YUV colors
-        convert to RGB colors.
-
-        @param context         GPU context
-        @param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
-                               kRec709_SkYUVColorSpace
-        @param yuvTextures     array of YUV textures on GPU
-        @param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
-        @param backendTexture  the resource that stores the final pixels
-        @param imageColorSpace range of colors; may be nullptr
-        @return                created SkImage, or nullptr
+    /** To be deprecated.
     */
     static sk_sp<SkImage> MakeFromYUVTexturesCopyWithExternalBackend(
             GrContext* context, SkYUVColorSpace yuvColorSpace,
             const GrBackendTexture yuvTextures[3], GrSurfaceOrigin imageOrigin,
             const GrBackendTexture& backendTexture, sk_sp<SkColorSpace> imageColorSpace = nullptr);
 
     /** Creates SkImage from copy of nv12Textures, an array of textures on GPU.
         nv12Textures[0] contains pixels for YUV component y plane.
@@ -481,17 +542,17 @@ public:
         @return            created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,
                                           const SkMatrix* matrix, const SkPaint* paint,
                                           BitDepth bitDepth,
                                           sk_sp<SkColorSpace> colorSpace);
 
 #if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
-    /** (see skbug.com/7447)
+    /** (See Skia bug 7447)
         Creates SkImage from Android hardware buffer.
         Returned SkImage takes a reference on the buffer.
 
         Only available on Android, when __ANDROID_API__ is defined to be 26 or greater.
 
         @param hardwareBuffer  AHardwareBuffer Android hardware buffer
         @param alphaType       one of:
                                kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
@@ -500,16 +561,32 @@ public:
         @param surfaceOrigin   one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
         @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromAHardwareBuffer(
             AHardwareBuffer* hardwareBuffer,
             SkAlphaType alphaType = kPremul_SkAlphaType,
             sk_sp<SkColorSpace> colorSpace = nullptr,
             GrSurfaceOrigin surfaceOrigin = kTopLeft_GrSurfaceOrigin);
+
+    /** Creates SkImage from Android hardware buffer and uploads the data from the SkPixmap to it.
+        Returned SkImage takes a reference on the buffer.
+
+        Only available on Android, when __ANDROID_API__ is defined to be 26 or greater.
+
+        @param pixmap          SkPixmap that contains data to be uploaded to the AHardwareBuffer
+        @param hardwareBuffer  AHardwareBuffer Android hardware buffer
+        @param surfaceOrigin   one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromAHardwareBufferWithData(
+            GrContext* context,
+            const SkPixmap& pixmap,
+            AHardwareBuffer* hardwareBuffer,
+            GrSurfaceOrigin surfaceOrigin = kTopLeft_GrSurfaceOrigin);
 #endif
 
     /** Returns pixel count in each row.
 
         @return  pixel width in SkImage
     */
     int width() const { return fWidth; }
 
@@ -765,18 +842,18 @@ public:
         If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
         match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
         false if pixel conversion is not possible.
 
         Scales the image, with filterQuality, to match dst.width() and dst.height().
         filterQuality kNone_SkFilterQuality is fastest, typically implemented with
         nearest neighbor filter. kLow_SkFilterQuality is typically implemented with
         bilerp filter. kMedium_SkFilterQuality is typically implemented with
-        bilerp filter, and Filter_Quality_MipMap when size is reduced.
-        kHigh_SkFilterQuality is slowest, typically implemented with Filter_Quality_BiCubic.
+        bilerp filter, and mip-map filter when size is reduced.
+        kHigh_SkFilterQuality is slowest, typically implemented with bicubic filter.
 
         If cachingHint is kAllow_CachingHint, pixels may be retained locally.
         If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
 
         @param dst            destination SkPixmap: SkImageInfo, pixels, row bytes
         @param filterQuality  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
                               kMedium_SkFilterQuality, kHigh_SkFilterQuality
         @param cachingHint    one of: kAllow_CachingHint, kDisallow_CachingHint
@@ -887,23 +964,31 @@ public:
         and offset are undefined.
 
         Useful for animation of SkImageFilter that varies size from frame to frame.
         Returned SkImage is created larger than required by filter so that GPU texture
         can be reused with different sized effects. outSubset describes the valid bounds
         of GPU texture returned. offset translates the returned SkImage to keep subsequent
         animation frames aligned with respect to each other.
 
+        @param context     the GrContext in play - if it exists
         @param filter      how SkImage is sampled when transformed
         @param subset      bounds of SkImage processed by filter
         @param clipBounds  expected bounds of filtered SkImage
         @param outSubset   storage for returned SkImage bounds
         @param offset      storage for returned SkImage translation
         @return            filtered SkImage, or nullptr
     */
+    sk_sp<SkImage> makeWithFilter(GrContext* context,
+                                  const SkImageFilter* filter, const SkIRect& subset,
+                                  const SkIRect& clipBounds, SkIRect* outSubset,
+                                  SkIPoint* offset) const;
+
+    /** To be deprecated.
+    */
     sk_sp<SkImage> makeWithFilter(const SkImageFilter* filter, const SkIRect& subset,
                                   const SkIRect& clipBounds, SkIRect* outSubset,
                                   SkIPoint* offset) const;
 
     /** Defines a callback function, taking one parameter of type GrBackendTexture with
         no return value. Function is called when back-end texture is to be released.
     */
     typedef std::function<void(GrBackendTexture)> BackendTextureReleaseProc;
@@ -929,30 +1014,34 @@ public:
         @param backendTextureReleaseProc  storage for clean up function
         @return                           true if back-end texture was created
     */
     static bool MakeBackendTextureFromSkImage(GrContext* context,
                                               sk_sp<SkImage> image,
                                               GrBackendTexture* backendTexture,
                                               BackendTextureReleaseProc* backendTextureReleaseProc);
 
+    /** Deprecated.
+     */
     enum LegacyBitmapMode {
         kRO_LegacyBitmapMode, //!< returned bitmap is read-only and immutable
     };
 
-    /** Creates raster SkBitmap with same pixels as SkImage. If legacyBitmapMode is
+    /** Deprecated.
+        Creates raster SkBitmap with same pixels as SkImage. If legacyBitmapMode is
         kRO_LegacyBitmapMode, returned bitmap is read-only and immutable.
         Returns true if SkBitmap is stored in bitmap. Returns false and resets bitmap if
         SkBitmap write did not succeed.
 
         @param bitmap            storage for legacy SkBitmap
-        @param legacyBitmapMode  to be deprecated
+        @param legacyBitmapMode  bitmap is read-only and immutable
         @return                  true if SkBitmap was created
     */
-    bool asLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode legacyBitmapMode = kRO_LegacyBitmapMode) const;
+    bool asLegacyBitmap(SkBitmap* bitmap,
+                        LegacyBitmapMode legacyBitmapMode = kRO_LegacyBitmapMode) const;
 
     /** Returns true if SkImage is backed by an image-generator or other service that creates
         and caches its pixels or texture on-demand.
 
         @return  true if SkImage is created as needed
     */
     bool isLazyGenerated() const;
 
@@ -963,16 +1052,29 @@ public:
         Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.
         If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.
 
         @param target  SkColorSpace describing color range of returned SkImage
         @return        created SkImage in target SkColorSpace
     */
     sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target) const;
 
+    /** Experimental.
+        Creates SkImage in target SkColorType and SkColorSpace.
+        Returns nullptr if SkImage could not be created.
+
+        Returns original SkImage if it is in target SkColorType and SkColorSpace.
+
+        @param targetColorType  SkColorType of returned SkImage
+        @param targetColorSpace SkColorSpace of returned SkImage
+        @return                 created SkImage in target SkColorType and SkColorSpace
+    */
+    sk_sp<SkImage> makeColorTypeAndColorSpace(SkColorType targetColorType,
+                                              sk_sp<SkColorSpace> targetColorSpace) const;
+
 private:
     SkImage(int width, int height, uint32_t uniqueID);
     friend class SkImage_Base;
 
     const int       fWidth;
     const int       fHeight;
     const uint32_t  fUniqueID;
 
--- a/gfx/skia/skia/include/core/SkImageEncoder.h
+++ b/gfx/skia/skia/include/core/SkImageEncoder.h
@@ -22,17 +22,18 @@
  * @param  quality range from 0-100, this is supported by jpeg and webp.
  *                 higher values correspond to improved visual quality, but less compression.
  *
  * @return false iff input is bad or format is unsupported.
  *
  * Will always return false if Skia is compiled without image
  * encoders.
  *
- * Note that webp encodes will use webp lossy compression.
+ * For SkEncodedImageFormat::kWEBP, if quality is 100, it will use lossless compression. Otherwise
+ * it will use lossy.
  *
  * For examples of encoding an image to a file or to a block of memory,
  * see tools/sk_tool_utils.h.
  */
 SK_API bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
                           SkEncodedImageFormat format, int quality);
 
 /**
@@ -51,17 +52,18 @@ inline bool SkEncodeImage(SkWStream* dst
  * @param  quality range from 0-100, this is supported by jpeg and webp.
  *                 higher values correspond to improved visual quality, but less compression.
  *
  * @return encoded data or nullptr if input is bad or format is unsupported.
  *
  * Will always return nullptr if Skia is compiled without image
  * encoders.
  *
- * Note that webp encodes will use webp lossy compression.
+ * For SkEncodedImageFormat::kWEBP, if quality is 100, it will use lossless compression. Otherwise
+ * it will use lossy.
  */
 SK_API sk_sp<SkData> SkEncodePixmap(const SkPixmap& src, SkEncodedImageFormat format, int quality);
 
 /**
  *  Helper that extracts the pixmap from the bitmap, and then calls SkEncodePixmap()
  */
 SK_API sk_sp<SkData> SkEncodeBitmap(const SkBitmap& src, SkEncodedImageFormat format, int quality);
 
--- a/gfx/skia/skia/include/core/SkImageFilter.h
+++ b/gfx/skia/skia/include/core/SkImageFilter.h
@@ -13,21 +13,21 @@
 #include "../private/SkMutex.h"
 #include "SkColorSpace.h"
 #include "SkFilterQuality.h"
 #include "SkFlattenable.h"
 #include "SkImageInfo.h"
 #include "SkMatrix.h"
 #include "SkRect.h"
 
-class GrContext;
 class GrFragmentProcessor;
 class SkColorFilter;
 class SkColorSpaceXformer;
 struct SkIPoint;
+class GrRecordingContext;
 class SkSpecialImage;
 class SkImageFilterCache;
 struct SkImageFilterCacheKey;
 
 /**
  *  Base class for image filters. If one is installed in the paint, then
  *  all drawing occurs as usual, but it is as if the drawing happened into an
  *  offscreen (before the xfermode is applied). This offscreen bitmap will
@@ -162,17 +162,17 @@ public:
      * In kReverse mode, 'inputRect' is the device-space bounds of the input pixels. In kForward
      * mode it should always be null. If 'inputRect' is null in kReverse mode the resulting
      * answer may be incorrect.
      */
     SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm,
                          MapDirection, const SkIRect* inputRect = nullptr) const;
 
 #if SK_SUPPORT_GPU
-    static sk_sp<SkSpecialImage> DrawWithFP(GrContext* context,
+    static sk_sp<SkSpecialImage> DrawWithFP(GrRecordingContext* context,
                                             std::unique_ptr<GrFragmentProcessor> fp,
                                             const SkIRect& bounds,
                                             const OutputProperties& outputProperties);
 #endif
 
     /**
      *  Returns whether this image filter is a color filter and puts the color filter into the
      *  "filterPtr" parameter if it can. Does nothing otherwise.
@@ -247,17 +247,17 @@ public:
 
     /**
      * Return an imagefilter which transforms its input by the given matrix.
      */
     static sk_sp<SkImageFilter> MakeMatrixFilter(const SkMatrix& matrix,
                                                  SkFilterQuality quality,
                                                  sk_sp<SkImageFilter> input);
 
-    static void InitializeFlattenables();
+    static void RegisterFlattenables();
 
     static SkFlattenable::Type GetFlattenableType() {
         return kSkImageFilter_Type;
     }
 
     SkFlattenable::Type getFlattenableType() const override {
         return kSkImageFilter_Type;
     }
--- a/gfx/skia/skia/include/core/SkImageGenerator.h
+++ b/gfx/skia/skia/include/core/SkImageGenerator.h
@@ -7,20 +7,20 @@
 
 #ifndef SkImageGenerator_DEFINED
 #define SkImageGenerator_DEFINED
 
 #include "SkBitmap.h"
 #include "SkColor.h"
 #include "SkImage.h"
 #include "SkImageInfo.h"
-#include "SkYUVSizeInfo.h"
+#include "SkYUVAIndex.h"
+#include "SkYUVASizeInfo.h"
 
-class GrContext;
-class GrContextThreadSafeProxy;
+class GrRecordingContext;
 class GrTextureProxy;
 class GrSamplerState;
 class SkBitmap;
 class SkData;
 class SkMatrix;
 class SkPaint;
 class SkPicture;
 
@@ -81,33 +81,40 @@ public:
      *  @return true on success.
      */
     bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
 
     /**
      *  If decoding to YUV is supported, this returns true.  Otherwise, this
      *  returns false and does not modify any of the parameters.
      *
-     *  @param sizeInfo   Output parameter indicating the sizes and required
-     *                    allocation widths of the Y, U, and V planes.
-     *  @param colorSpace Output parameter.
+     *  @param sizeInfo    Output parameter indicating the sizes and required
+     *                     allocation widths of the Y, U, V, and A planes.
+     *  @param yuvaIndices How the YUVA planes are organized/used
+     *  @param colorSpace  Output parameter.
      */
-    bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const;
+    bool queryYUVA8(SkYUVASizeInfo* sizeInfo,
+                    SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
+                    SkYUVColorSpace* colorSpace) const;
 
     /**
      *  Returns true on success and false on failure.
      *  This always attempts to perform a full decode.  If the client only
-     *  wants size, it should call queryYUV8().
+     *  wants size, it should call queryYUVA8().
      *
-     *  @param sizeInfo   Needs to exactly match the values returned by the
-     *                    query, except the WidthBytes may be larger than the
-     *                    recommendation (but not smaller).
-     *  @param planes     Memory for each of the Y, U, and V planes.
+     *  @param sizeInfo    Needs to exactly match the values returned by the
+     *                     query, except the WidthBytes may be larger than the
+     *                     recommendation (but not smaller).
+     *  @param yuvaIndices Needs to exactly match the values returned by the query.
+     *  @param planes      Memory for the Y, U, V, and A planes. Note that, depending on the
+     *                     settings in yuvaIndices, anywhere from 1..4 planes could be returned.
      */
-    bool getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]);
+    bool getYUVA8Planes(const SkYUVASizeInfo& sizeInfo,
+                        const SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
+                        void* planes[]);
 
 #if SK_SUPPORT_GPU
     /**
      *  If the generator can natively/efficiently return its pixels as a GPU image (backed by a
      *  texture) this will return that image. If not, this will return NULL.
      *
      *  This routine also supports retrieving only a subset of the pixels. That subset is specified
      *  by the following rectangle:
@@ -127,17 +134,17 @@ public:
      *  - its internal context is the same
      *  - it can somehow convert its texture into one that is valid for the provided context.
      *
      *  If the willNeedMipMaps flag is true, the generator should try to create a TextureProxy that
      *  at least has the mip levels allocated and the base layer filled in. If this is not possible,
      *  the generator is allowed to return a non mipped proxy, but this will have some additional
      *  overhead in later allocating mips and copying of the base layer.
      */
-    sk_sp<GrTextureProxy> generateTexture(GrContext*, const SkImageInfo& info,
+    sk_sp<GrTextureProxy> generateTexture(GrRecordingContext*, const SkImageInfo& info,
                                           const SkIPoint& origin,
                                           bool willNeedMipMaps);
 #endif
 
     /**
      *  If the default image decoder system can interpret the specified (encoded) data, then
      *  this returns a new ImageGenerator for it. Otherwise this returns NULL. Either way
      *  the caller is still responsible for managing their ownership of the data.
@@ -158,28 +165,30 @@ protected:
     static constexpr int kNeedNewImageUniqueID = 0;
 
     SkImageGenerator(const SkImageInfo& info, uint32_t uniqueId = kNeedNewImageUniqueID);
 
     virtual sk_sp<SkData> onRefEncodedData() { return nullptr; }
     struct Options {};
     virtual bool onGetPixels(const SkImageInfo&, void*, size_t, const Options&) { return false; }
     virtual bool onIsValid(GrContext*) const { return true; }
-    virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const { return false; }
-    virtual bool onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) { return false; }
-
+    virtual bool onQueryYUVA8(SkYUVASizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount],
+                              SkYUVColorSpace*) const { return false; }
+    virtual bool onGetYUVA8Planes(const SkYUVASizeInfo&, const SkYUVAIndex[SkYUVAIndex::kIndexCount],
+                                  void*[4] /*planes*/) { return false; }
 #if SK_SUPPORT_GPU
     enum class TexGenType {
         kNone,           //image generator does not implement onGenerateTexture
         kCheap,          //onGenerateTexture is implemented and it is fast (does not render offscreen)
         kExpensive,      //onGenerateTexture is implemented and it is relatively slow
     };
 
     virtual TexGenType onCanGenerateTexture() const { return TexGenType::kNone; }
-    virtual sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,
+    virtual sk_sp<GrTextureProxy> onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
+                                                    const SkIPoint&,
                                                     bool willNeedMipMaps);  // returns nullptr
 #endif
 
 private:
     const SkImageInfo fInfo;
     const uint32_t fUniqueID;
 
     friend class SkImage_Lazy;
--- a/gfx/skia/skia/include/core/SkImageInfo.h
+++ b/gfx/skia/skia/include/core/SkImageInfo.h
@@ -87,17 +87,18 @@ enum SkColorType {
     kRGB_565_SkColorType,      //!< pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
     kARGB_4444_SkColorType,    //!< pixel with 4 bits for alpha, red, green, blue; in 16-bit word
     kRGBA_8888_SkColorType,    //!< pixel with 8 bits for red, green, blue, alpha; in 32-bit word
     kRGB_888x_SkColorType,     //!< pixel with 8 bits each for red, green, blue; in 32-bit word
     kBGRA_8888_SkColorType,    //!< pixel with 8 bits for blue, green, red, alpha; in 32-bit word
     kRGBA_1010102_SkColorType, //!< 10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
     kRGB_101010x_SkColorType,  //!< pixel with 10 bits each for red, green, blue; in 32-bit word
     kGray_8_SkColorType,       //!< pixel with grayscale level in 8-bit byte
-    kRGBA_F16_SkColorType,   //!< pixel with half floats for red, green, blue, alpha; in 64-bit word
+    kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha; in 64-bit word
+    kRGBA_F16_SkColorType,     //!< pixel with half floats for red, green, blue, alpha; in 64-bit word
     kRGBA_F32_SkColorType,     //!< pixel using C float for red, green, blue, alpha; in 128-bit word
     kLastEnum_SkColorType     = kRGBA_F32_SkColorType,//!< last valid value
 
 #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
     kN32_SkColorType          = kBGRA_8888_SkColorType,//!< native ARGB 32-bit encoding
 
 #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
     kN32_SkColorType          = kRGBA_8888_SkColorType,//!< native ARGB 32-bit encoding
@@ -456,18 +457,18 @@ public:
     }
 
     /** Creates SkImageInfo with same SkAlphaType, SkColorSpace, width, and height,
         with SkColorType set to newColorType.
 
         @param newColorType  one of:
                              kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
                              kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
-                             kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
-                             kGray_8_SkColorType, kRGBA_F16_SkColorType
+                             kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType,
+                             kRGB_101010x_SkColorType, kGray_8_SkColorType, kRGBA_F16_SkColorType
         @return              created SkImageInfo
     */
     SkImageInfo makeColorType(SkColorType newColorType) const {
         return Make(this->width(), this->height(), newColorType, fAlphaType, fColorSpace);
     }
 
     /** Creates SkImageInfo with same SkAlphaType, SkColorType, width, and height,
         with SkColorSpace set to cs.
--- a/gfx/skia/skia/include/core/SkMaskFilter.h
+++ b/gfx/skia/skia/include/core/SkMaskFilter.h
@@ -65,13 +65,13 @@ public:
     static sk_sp<SkMaskFilter> Deserialize(const void* data, size_t size,
                                           const SkDeserialProcs* procs = nullptr) {
         return sk_sp<SkMaskFilter>(static_cast<SkMaskFilter*>(
                                   SkFlattenable::Deserialize(
                                   kSkMaskFilter_Type, data, size, procs).release()));
     }
 
 private:
-    static void InitializeFlattenables();
+    static void RegisterFlattenables();
     friend class SkFlattenable;
 };
 
 #endif
--- a/gfx/skia/skia/include/core/SkMatrix.h
+++ b/gfx/skia/skia/include/core/SkMatrix.h
@@ -550,36 +550,36 @@ public:
     */
     void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); }
 
     /** Sets SkMatrix to scale by sx and sy, about a pivot point at (px, py).
         The pivot point is unchanged when mapped with SkMatrix.
 
         @param sx  horizontal scale factor
         @param sy  vertical scale factor
-        @param px  pivot x
-        @param py  pivot y
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
     */
     void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to scale by sx and sy about at pivot point at (0, 0).
 
         @param sx  horizontal scale factor
         @param sy  vertical scale factor
     */
     void setScale(SkScalar sx, SkScalar sy);
 
     /** Sets SkMatrix to rotate by degrees about a pivot point at (px, py).
         The pivot point is unchanged when mapped with SkMatrix.
 
         Positive degrees rotates clockwise.
 
         @param degrees  angle of axes relative to upright axes
-        @param px       pivot x
-        @param py       pivot y
+        @param px       pivot on x-axis
+        @param py       pivot on y-axis
     */
     void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to rotate by degrees about a pivot point at (0, 0).
         Positive degrees rotates clockwise.
 
         @param degrees  angle of axes relative to upright axes
     */
@@ -588,18 +588,18 @@ public:
     /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (px, py).
         The pivot point is unchanged when mapped with SkMatrix.
 
         Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
         Vector length specifies scale.
 
         @param sinValue  rotation vector x-axis component
         @param cosValue  rotation vector y-axis component
-        @param px        pivot x-axis
-        @param py        pivot y-axis
+        @param px        pivot on x-axis
+        @param py        pivot on y-axis
     */
     void setSinCos(SkScalar sinValue, SkScalar cosValue,
                    SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (0, 0).
 
         Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
         Vector length specifies scale.
@@ -620,18 +620,18 @@ public:
     */
     SkMatrix& setRSXform(const SkRSXform& rsxForm);
 
     /** Sets SkMatrix to skew by kx and ky, about a pivot point at (px, py).
         The pivot point is unchanged when mapped with SkMatrix.
 
         @param kx  horizontal skew factor
         @param ky  vertical skew factor
-        @param px  pivot x
-        @param py  pivot y
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
     */
     void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to skew by kx and ky, about a pivot point at (0, 0).
 
         @param kx  horizontal skew factor
         @param ky  vertical skew factor
     */
@@ -694,18 +694,18 @@ public:
         sets SkMatrix to:
 
                                          | A B C | | sx  0 dx |   | A*sx B*sy A*dx+B*dy+C |
             Matrix * S(sx, sy, px, py) = | D E F | |  0 sy dy | = | D*sx E*sy D*dx+E*dy+F |
                                          | G H I | |  0  0  1 |   | G*sx H*sy G*dx+H*dy+I |
 
         @param sx  horizontal scale factor
         @param sy  vertical scale factor
-        @param px  pivot x
-        @param py  pivot y
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
     */
     void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)
         about pivot point (0, 0).
         This can be thought of as scaling about the origin before applying SkMatrix.
 
         Given:
@@ -746,18 +746,18 @@ public:
 
         sets SkMatrix to:
 
                                           | A B C | | c -s dx |   | Ac+Bs -As+Bc A*dx+B*dy+C |
             Matrix * R(degrees, px, py) = | D E F | | s  c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F |
                                           | G H I | | 0  0  1 |   | Gc+Hs -Gs+Hc G*dx+H*dy+I |
 
         @param degrees  angle of axes relative to upright axes
-        @param px       pivot x
-        @param py       pivot y
+        @param px       pivot on x-axis
+        @param py       pivot on y-axis
     */
     void preRotate(SkScalar degrees, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees
         about pivot point (0, 0).
         This can be thought of as rotating about the origin before applying SkMatrix.
 
         Positive degrees rotates clockwise.
@@ -801,18 +801,18 @@ public:
         sets SkMatrix to:
 
                                          | A B C | |  1 kx dx |   | A+B*ky A*kx+B A*dx+B*dy+C |
             Matrix * K(kx, ky, px, py) = | D E F | | ky  1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F |
                                          | G H I | |  0  0  1 |   | G+H*ky G*kx+H G*dx+H*dy+I |
 
         @param kx  horizontal skew factor
         @param ky  vertical skew factor
-        @param px  pivot x
-        @param py  pivot y
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
     */
     void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)
         about pivot point (0, 0).
         This can be thought of as skewing about the origin before applying SkMatrix.
 
         Given:
@@ -889,18 +889,18 @@ public:
         sets SkMatrix to:
 
                                          | sx  0 dx | | J K L |   | sx*J+dx*P sx*K+dx*Q sx*L+dx+R |
             S(sx, sy, px, py) * Matrix = |  0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R |
                                          |  0  0  1 | | P Q R |   |         P         Q         R |
 
         @param sx  horizontal scale factor
         @param sy  vertical scale factor
-        @param px  pivot x
-        @param py  pivot y
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
     */
     void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point
         (0, 0), multiplied by SkMatrix.
         This can be thought of as scaling about the origin after applying SkMatrix.
 
         Given:
@@ -969,18 +969,18 @@ public:
 
         sets SkMatrix to:
 
                                           |c -s dx| |J K L|   |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R|
             R(degrees, px, py) * Matrix = |s  c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R|
                                           |0  0  1| |P Q R|   |         P          Q          R|
 
         @param degrees  angle of axes relative to upright axes
-        @param px       pivot x
-        @param py       pivot y
+        @param px       pivot on x-axis
+        @param py       pivot on y-axis
     */
     void postRotate(SkScalar degrees, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point
         (0, 0), multiplied by SkMatrix.
         This can be thought of as rotating about the origin after applying SkMatrix.
 
         Positive degrees rotates clockwise.
@@ -1024,18 +1024,18 @@ public:
         sets SkMatrix to:
 
                                          | 1 kx dx| |J K L|   |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R|
             K(kx, ky, px, py) * Matrix = |ky  1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R|
                                          | 0  0  1| |P Q R|   |          P           Q           R|
 
         @param kx  horizontal skew factor
         @param ky  vertical skew factor
-        @param px  pivot x
-        @param py  pivot y
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
     */
     void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
 
     /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point
         (0, 0), multiplied by SkMatrix.
         This can be thought of as skewing about the origin after applying SkMatrix.
 
         Given:
@@ -1160,47 +1160,47 @@ public:
     }
 
     /** Fills affine with identity values in column major order.
         Sets affine to:
 
             | 1 0 0 |
             | 0 1 0 |
 
-        Affine 3x2 matrices in column major order are used by OpenGL and XPS.
+        Affine 3 by 2 matrices in column major order are used by OpenGL and XPS.
 
-        @param affine  storage for 3x2 affine matrix
+        @param affine  storage for 3 by 2 affine matrix
     */
     static void SetAffineIdentity(SkScalar affine[6]);
 
     /** Fills affine in column major order. Sets affine to:
 
             | scale-x  skew-x translate-x |
             | skew-y  scale-y translate-y |
 
         If SkMatrix contains perspective, returns false and leaves affine unchanged.
 
-        @param affine  storage for 3x2 affine matrix; may be nullptr
+        @param affine  storage for 3 by 2 affine matrix; may be nullptr
         @return        true if SkMatrix does not contain perspective
     */
     bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const;
 
     /** Sets SkMatrix to affine values, passed in column major order. Given affine,
         column, then row, as:
 
             | scale-x  skew-x translate-x |
             |  skew-y scale-y translate-y |
 
         SkMatrix is set, row, then column, to:
 
             | scale-x  skew-x translate-x |
             |  skew-y scale-y translate-y |
             |       0       0           1 |
 
-        @param affine  3x2 affine matrix
+        @param affine  3 by 2 affine matrix
     */
     void setAffine(const SkScalar affine[6]);
 
     /** Maps src SkPoint array of length count to dst SkPoint array of equal or greater
         length. SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given:
 
                      | A B C |        | x |
             Matrix = | D E F |,  pt = | y |
@@ -1220,22 +1220,17 @@ public:
                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
 
         src and dst may point to the same storage.
 
         @param dst    storage for mapped SkPoint
         @param src    SkPoint to transform
         @param count  number of SkPoint to transform
     */
-    void mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
-        SkASSERT((dst && src && count > 0) || 0 == count);
-        // no partial overlap
-        SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
-        this->getMapPtsProc()(*this, dst, src, count);
-    }
+    void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
 
     /** Maps pts SkPoint array of length count in place. SkPoint are mapped by multiplying
         each SkPoint by SkMatrix. Given:
 
                      | A B C |        | x |
             Matrix = | D E F |,  pt = | y |
                      | G H I |        | 1 |
 
@@ -1289,20 +1284,17 @@ public:
                           |A B C| |x|                               Ax+By+C   Dx+Ey+F
             Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
 
         @param x       x-axis value of SkPoint to map
         @param y       y-axis value of SkPoint to map
         @param result  storage for mapped SkPoint
     */
-    void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
-        SkASSERT(result);
-        this->getMapXYProc()(*this, x, y, result);
-    }
+    void mapXY(SkScalar x, SkScalar y, SkPoint* result) const;
 
     /** Returns SkPoint (x, y) multiplied by SkMatrix. Given:
 
                      | A B C |        | x |
             Matrix = | D E F |,  pt = | y |
                      | G H I |        | 1 |
 
         result is computed as:
@@ -1312,17 +1304,17 @@ public:
                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
 
         @param x  x-axis value of SkPoint to map
         @param y  y-axis value of SkPoint to map
         @return   mapped SkPoint
     */
     SkPoint mapXY(SkScalar x, SkScalar y) const {
         SkPoint result;
-        this->getMapXYProc()(*this, x, y, &result);
+        this->mapXY(x,y, &result);
         return result;
     }
 
     /** Maps src vector array of length count to vector SkPoint array of equal or greater
         length. Vectors are mapped by multiplying each vector by SkMatrix, treating
         SkMatrix translation as zero. Given:
 
                      | A B 0 |         | x |
@@ -1372,17 +1364,17 @@ public:
 
         @param vecs   vectors to transform, and storage for mapped vectors
         @param count  number of vectors to transform
     */
     void mapVectors(SkVector vecs[], int count) const {
         this->mapVectors(vecs, vecs, count);
     }
 
-    /** Maps vector (x, y) to result. Vector is mapped by multiplying by SkMatrix,
+    /** Maps vector (dx, dy) to result. Vector is mapped by multiplying by SkMatrix,
         treating SkMatrix translation as zero. Given:
 
                      | A B 0 |         | dx |
             Matrix = | D E 0 |,  vec = | dy |
                      | G H I |         |  1 |
 
         each result vector is computed as:
 
@@ -1394,17 +1386,17 @@ public:
         @param dy      y-axis value of vector to map
         @param result  storage for mapped vector
     */
     void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const {
         SkVector vec = { dx, dy };
         this->mapVectors(result, &vec, 1);
     }
 
-    /** Returns vector (x, y) multiplied by SkMatrix, treating SkMatrix translation as zero.
+    /** Returns vector (dx, dy) multiplied by SkMatrix, treating SkMatrix translation as zero.
         Given:
 
                      | A B 0 |         | dx |
             Matrix = | D E 0 |,  vec = | dy |
                      | G H I |         |  1 |
 
         each result vector is computed as:
 
@@ -1434,17 +1426,17 @@ public:
     bool mapRect(SkRect* dst, const SkRect& src) const;
 
     /** Sets rect to bounds of rect corners mapped by SkMatrix.
         Returns true if mapped corners are computed rect corners.
 
         Returned value is the same as calling rectStaysRect().
 
         @param rect  rectangle to map, and storage for bounds of mapped corners
-        @return      true if result is equivalent to mapped src
+        @return      true if result is equivalent to mapped rect
     */
     bool mapRect(SkRect* rect) const {
         return this->mapRect(rect, *rect);
     }
 
     /** Returns bounds of src corners mapped by SkMatrix.
 
         @param src  rectangle to map
--- a/gfx/skia/skia/include/core/SkMilestone.h
+++ b/gfx/skia/skia/include/core/SkMilestone.h
@@ -1,9 +1,9 @@
 /*
  * Copyright 2016 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 #ifndef SK_MILESTONE
-#define SK_MILESTONE 71
+#define SK_MILESTONE 74
 #endif
--- a/gfx/skia/skia/include/core/SkOverdrawCanvas.h
+++ b/gfx/skia/skia/include/core/SkOverdrawCanvas.h
@@ -16,57 +16,54 @@
  *  increments the alpha channel of each pixel every time it would have been touched
  *  by a draw call.  This is useful for detecting overdraw.
  */
 class SK_API SkOverdrawCanvas : public SkCanvasVirtualEnforcer<SkNWayCanvas> {
 public:
     /* Does not take ownership of canvas */
     SkOverdrawCanvas(SkCanvas*);
 
-    void onDrawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override;
-    void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint&) override;
-    void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override;
-    void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,
-                           const SkPaint&) override;
     void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;
     void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,
                      const SkPaint&) override;
     void onDrawPaint(const SkPaint&) override;
     void onDrawRect(const SkRect&, const SkPaint&) override;
+    void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override;
     void onDrawRegion(const SkRegion&, const SkPaint&) override;
     void onDrawOval(const SkRect&, const SkPaint&) override;
     void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
     void onDrawRRect(const SkRRect&, const SkPaint&) override;
     void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override;
     void onDrawVerticesObject(const SkVertices*, const SkVertices::Bone bones[], int boneCount,
                               SkBlendMode, const SkPaint&) override;
     void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
                      int, SkBlendMode, const SkRect*, const SkPaint*) override;
     void onDrawPath(const SkPath&, const SkPaint&) override;
     void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override;
     void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
                          SrcRectConstraint) override;
     void onDrawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*) override;
     void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&, const SkPaint*) override;
+    void onDrawImageSet(const ImageSetEntry[], int count, SkFilterQuality, SkBlendMode) override;
     void onDrawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint*) override;
     void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
                           SrcRectConstraint) override;
     void onDrawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&, const SkPaint*) override;
     void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&,
                              const SkPaint*) override;
     void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
     void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
 
     void onDrawAnnotation(const SkRect&, const char key[], SkData* value) override;
     void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
 
 private:
-    void drawPosTextCommon(const void*, size_t, const SkScalar[], int, const SkPoint&,
-                           const SkPaint&);
+    void drawPosTextCommon(const SkGlyphID[], int, const SkScalar[], int, const SkPoint&,
+                           const SkFont&, const SkPaint&);
 
     inline SkPaint overdrawPaint(const SkPaint& paint);
 
     SkPaint   fPaint;
 
     typedef SkCanvasVirtualEnforcer<SkNWayCanvas> INHERITED;
 };
 
--- a/gfx/skia/skia/include/core/SkPaint.h
+++ b/gfx/skia/skia/include/core/SkPaint.h
@@ -17,81 +17,48 @@
 
 #ifndef SkPaint_DEFINED
 #define SkPaint_DEFINED
 
 #include "../private/SkTo.h"
 #include "SkBlendMode.h"
 #include "SkColor.h"
 #include "SkFilterQuality.h"
-#include "SkMatrix.h"
 #include "SkRefCnt.h"
 
-class GrTextBlob;
-class SkAutoDescriptor;
 class SkColorFilter;
 class SkColorSpace;
-class SkData;
-class SkDescriptor;
 class SkDrawLooper;
-class SkGlyph;
-class SkGlyphRunBuilder;
-class SkGlyphRun;
-class SkGlyphRunListPainter;
 struct SkRect;
-class SkGlyphCache;
 class SkImageFilter;
 class SkMaskFilter;
 class SkPath;
 class SkPathEffect;
-struct SkPoint;
-class SkRunFont;
 class SkShader;
-class SkSurfaceProps;
-class SkTextBlob;
-class SkTextBlobRunIterator;
-class SkTypeface;
 
 /** \class SkPaint
-    SkPaint controls options applied when drawing and measuring. SkPaint collects all
+    SkPaint controls options applied when drawing. SkPaint collects all
     options outside of the SkCanvas clip and SkCanvas matrix.
 
-    Various options apply to text, strokes and fills, and images.
-
-    Some options may not be implemented on all platforms; in these cases, setting
-    the option has no effect. Some options are conveniences that duplicate SkCanvas
-    functionality; for instance, text size is identical to matrix scale.
-
-    SkPaint options are rarely exclusive; each option modifies a stage of the drawing
-    pipeline and multiple pipeline stages may be affected by a single SkPaint.
+    Various options apply to strokes and fills, and images.
 
     SkPaint collects effects and filters that describe single-pass and multiple-pass
     algorithms that alter the drawing geometry, color, and transparency. For instance,
     SkPaint does not directly implement dashing or blur, but contains the objects that do so.
-
-    The objects contained by SkPaint are opaque, and cannot be edited outside of the SkPaint
-    to affect it. The implementation is free to defer computations associated with the
-    SkPaint, or ignore them altogether. For instance, some GPU implementations draw all
-    SkPath geometries with anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
-    is set in SkPaint.
-
-    SkPaint describes a single color, a single font, a single image quality, and so on.
-    Multiple colors are drawn either by using multiple paints or with objects like
-    SkShader attached to SkPaint.
 */
 class SK_API SkPaint {
 public:
 
     /** Constructs SkPaint with default values.
 
         @return  default initialized SkPaint
     */
     SkPaint();
 
-    /** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,
+    /** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
         SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared
         between the original paint and the copy. Objects containing SkRefCnt increment
         their references by one.
 
         The referenced objects SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
         SkDrawLooper, and SkImageFilter cannot be modified after they are created.
         This prevents objects with SkRefCnt from being modified once SkPaint refers to them.
 
@@ -105,23 +72,23 @@ public:
 
         After the call, paint is undefined, and can be safely destructed.
 
         @param paint  original to move
         @return       content of paint
     */
     SkPaint(SkPaint&& paint);
 
-    /** Decreases SkPaint SkRefCnt of owned objects: SkTypeface, SkPathEffect, SkShader,
+    /** Decreases SkPaint SkRefCnt of owned objects: SkPathEffect, SkShader,
         SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter. If the
         objects containing SkRefCnt go to zero, they are deleted.
     */
     ~SkPaint();
 
-    /** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,
+    /** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
         SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared
         between the original paint and the copy. Objects containing SkRefCnt in the
         prior destination are decreased by one, and the referenced objects are deleted if the
         resulting count is zero. Objects containing SkRefCnt in the parameter paint
         are increased by one. paint is unmodified.
 
         @param paint  original to copy
         @return       content of paint
@@ -136,27 +103,27 @@ public:
         After the call, paint is undefined, and can be safely destructed.
 
         @param paint  original to move
         @return       content of paint
     */
     SkPaint& operator=(SkPaint&& paint);
 
     /** Compares a and b, and returns true if a and b are equivalent. May return false
-        if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
+        if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
         SkDrawLooper, or SkImageFilter have identical contents but different pointers.
 
         @param a  SkPaint to compare
         @param b  SkPaint to compare
         @return   true if SkPaint pair are equivalent
     */
     SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
 
     /** Compares a and b, and returns true if a and b are not equivalent. May return true
-        if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
+        if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
         SkDrawLooper, or SkImageFilter have identical contents but different pointers.
 
         @param a  SkPaint to compare
         @param b  SkPaint to compare
         @return   true if SkPaint pair are not equivalent
     */
     friend bool operator!=(const SkPaint& a, const SkPaint& b) {
         return !(a == b);
@@ -176,277 +143,40 @@ public:
     */
     uint32_t getHash() const;
 
     /** Sets all SkPaint contents to their initial values. This is equivalent to replacing
         SkPaint with the result of SkPaint().
     */
     void reset();
 
-    /** \enum SkPaint::Hinting
-        Hinting adjusts the glyph outlines so that the shape provides a uniform
-        look at a given point size on font engines that support it. Hinting may have a
-        muted effect or no effect at all depending on the platform.
-
-        The four levels roughly control corresponding features on platforms that use FreeType
-        as the font engine.
+    /** Returns true if pixels on the active edges of SkPath may be drawn with partial transparency.
+        @return  antialiasing state
     */
-    enum Hinting {
-        kNo_Hinting     = 0, //!< glyph outlines unchanged
-        kSlight_Hinting = 1, //!< minimal modification to improve constrast
-        kNormal_Hinting = 2, //!< glyph outlines modified to improve constrast
-        kFull_Hinting   = 3, //!< modifies glyph outlines for maximum constrast
-    };
-
-    /** Returns level of glyph outline adjustment.
-
-        @return  one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting
-    */
-    Hinting getHinting() const {
-        return static_cast<Hinting>(fBitfields.fHinting);
+    bool isAntiAlias() const {
+        return SkToBool(fBitfields.fAntiAlias);
     }
 
-    /** Sets level of glyph outline adjustment.
-        Does not check for valid values of hintingLevel.
-
-        @param hintingLevel  one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting
-    */
-    void setHinting(Hinting hintingLevel);
-
-    /** \enum SkPaint::Flags
-        The bit values stored in Flags.
-        The default value for Flags, normally zero, can be changed at compile time
-        with a custom definition of SkPaintDefaults_Flags.
-        All flags can be read and written explicitly; Flags allows manipulating
-        multiple settings at once.
+    /** Requests, but does not require, that edge pixels draw opaque or with
+        partial transparency.
+        @param aa  setting for antialiasing
     */
-    enum Flags {
-        kAntiAlias_Flag          = 0x01,   //!< mask for setting anti-alias
-        kDither_Flag             = 0x04,   //!< mask for setting dither
-        kFakeBoldText_Flag       = 0x20,   //!< mask for setting fake bold
-        kLinearText_Flag         = 0x40,   //!< mask for setting linear text
-        kSubpixelText_Flag       = 0x80,   //!< mask for setting subpixel text
-        kLCDRenderText_Flag      = 0x200,  //!< mask for setting LCD text
-        kEmbeddedBitmapText_Flag = 0x400,  //!< mask for setting font embedded bitmaps
-        kAutoHinting_Flag        = 0x800,  //!< mask for setting auto-hinting
-        kVerticalText_Flag       = 0x1000, //!< mask for setting vertical text
-        kAllFlags                = 0xFFFF, //!< mask of all Flags
-    };
-
-    #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
-    enum ReserveFlags {
-        kUnderlineText_ReserveFlag  = 0x08, //!< to be deprecated soon
-        kStrikeThruText_ReserveFlag = 0x10, //!< to be deprecated soon
-    };
-    #endif
-
-    /** Returns paint settings described by SkPaint::Flags. Each setting uses one
-        bit, and can be tested with SkPaint::Flags members.
-
-        @return  zero, one, or more bits described by SkPaint::Flags
-    */
-    uint32_t getFlags() const { return fBitfields.fFlags; }
-
-    /** Replaces SkPaint::Flags with flags, the union of the SkPaint::Flags members.
-        All SkPaint::Flags members may be cleared, or one or more may be set.
-
-        @param flags  union of SkPaint::Flags for SkPaint
-    */
-    void setFlags(uint32_t flags);
-
-    /** Returns true if pixels on the active edges of SkPath may be drawn with partial transparency.
-
-        Equivalent to getFlags() masked with kAntiAlias_Flag.
-
-        @return  kAntiAlias_Flag state
-    */
-    bool isAntiAlias() const {
-        return SkToBool(this->getFlags() & kAntiAlias_Flag);
-    }
-
-    /** Requests, but does not require, that SkPath edge pixels draw opaque or with
-        partial transparency.
-
-        Sets kAntiAlias_Flag if aa is true.
-        Clears kAntiAlias_Flag if aa is false.
-
-        @param aa  setting for kAntiAlias_Flag
-    */
-    void setAntiAlias(bool aa);
+    void setAntiAlias(bool aa) { fBitfields.fAntiAlias = static_cast<unsigned>(aa); }
 
     /** Returns true if color error may be distributed to smooth color transition.
-
-        Equivalent to getFlags() masked with kDither_Flag.
-
-        @return  kDither_Flag state
+        @return  dithering state
     */
     bool isDither() const {
-        return SkToBool(this->getFlags() & kDither_Flag);
+        return SkToBool(fBitfields.fDither);
     }
 
     /** Requests, but does not require, to distribute color error.
-
-        Sets kDither_Flag if dither is true.
-        Clears kDither_Flag if dither is false.
-
-        @param dither  setting for kDither_Flag
-    */
-    void setDither(bool dither);
-
-    /** Returns true if text is converted to SkPath before drawing and measuring.
-
-        Equivalent to getFlags() masked with kLinearText_Flag.
-
-        @return  kLinearText_Flag state
-    */
-    bool isLinearText() const {
-        return SkToBool(this->getFlags() & kLinearText_Flag);
-    }
-
-    /** Returns true if text is converted to SkPath before drawing and measuring.
-        By default, kLinearText_Flag is clear.
-
-        Sets kLinearText_Flag if linearText is true.
-        Clears kLinearText_Flag if linearText is false.
-
-        @param linearText  setting for kLinearText_Flag
-    */
-    void setLinearText(bool linearText);
-
-    /** Returns true if glyphs at different sub-pixel positions may differ on pixel edge coverage.
-
-        Equivalent to getFlags() masked with kSubpixelText_Flag.
-
-        @return  kSubpixelText_Flag state
-    */
-    bool isSubpixelText() const {
-        return SkToBool(this->getFlags() & kSubpixelText_Flag);
-    }
-
-    /** Requests, but does not require, that glyphs respect sub-pixel positioning.
-
-        Sets kSubpixelText_Flag if subpixelText is true.
-        Clears kSubpixelText_Flag if subpixelText is false.
-
-        @param subpixelText  setting for kSubpixelText_Flag
-    */
-    void setSubpixelText(bool subpixelText);
-
-    /** Returns true if glyphs may use LCD striping to improve glyph edges.
-
-        Returns true if SkPaint::Flags kLCDRenderText_Flag is set.
-
-        @return  kLCDRenderText_Flag state
-    */
-    bool isLCDRenderText() const {
-        return SkToBool(this->getFlags() & kLCDRenderText_Flag);
-    }
-
-    /** Requests, but does not require, that glyphs use LCD striping for glyph edges.
-
-        Sets kLCDRenderText_Flag if lcdText is true.
-        Clears kLCDRenderText_Flag if lcdText is false.
-
-        @param lcdText  setting for kLCDRenderText_Flag
-    */
-    void setLCDRenderText(bool lcdText);
-
-    /** Returns true if font engine may return glyphs from font bitmaps instead of from outlines.
-
-        Equivalent to getFlags() masked with kEmbeddedBitmapText_Flag.
-
-        @return  kEmbeddedBitmapText_Flag state
+        @param dither  setting for ditering
     */
-    bool isEmbeddedBitmapText() const {
-        return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);
-    }
-
-    /** Requests, but does not require, to use bitmaps in fonts instead of outlines.
-
-        Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
-        Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
-
-        @param useEmbeddedBitmapText  setting for kEmbeddedBitmapText_Flag
-    */
-    void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
-
-    /** Returns true if SkPaint::Hinting is set to kNormal_Hinting or kFull_Hinting, and if
-        platform uses FreeType as the font manager. If true, instructs
-        the font manager to always hint glyphs.
-
-        Equivalent to getFlags() masked with kAutoHinting_Flag.
-
-        @return  kAutoHinting_Flag state
-    */
-    bool isAutohinted() const {
-        return SkToBool(this->getFlags() & kAutoHinting_Flag);
-    }
-
-    /** Sets whether to always hint glyphs.
-        If SkPaint::Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
-        instructs the font manager to always hint glyphs.
-        auto-hinting has no effect if SkPaint::Hinting is set to kNo_Hinting or
-        kSlight_Hinting.
-
-        Only affects platforms that use FreeType as the font manager.
-
-        Sets kAutoHinting_Flag if useAutohinter is true.
-        Clears kAutoHinting_Flag if useAutohinter is false.
-
-        @param useAutohinter  setting for kAutoHinting_Flag
-    */
-    void setAutohinted(bool useAutohinter);
-
-    /** Returns true if glyphs are drawn top to bottom instead of left to right.
-
-        Equivalent to getFlags() masked with kVerticalText_Flag.
-
-        @return  kVerticalText_Flag state
-    */
-    bool isVerticalText() const {
-        return SkToBool(this->getFlags() & kVerticalText_Flag);
-    }
-
-    /** Returns true if text advance positions the next glyph below the previous glyph instead of to the
-        right of previous glyph.
-
-        Sets kVerticalText_Flag if vertical is true.
-        Clears kVerticalText_Flag if vertical is false.
-
-        @param verticalText  setting for kVerticalText_Flag
-    */
-    void setVerticalText(bool verticalText);
-
-    /** Returns true if approximate bold by increasing the stroke width when creating glyph bitmaps
-        from outlines.
-
-        Equivalent to getFlags() masked with kFakeBoldText_Flag.
-
-        @return  kFakeBoldText_Flag state
-    */
-    bool isFakeBoldText() const {
-        return SkToBool(this->getFlags() & kFakeBoldText_Flag);
-    }
-
-    /** Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
-
-        Sets kFakeBoldText_Flag if fakeBoldText is true.
-        Clears kFakeBoldText_Flag if fakeBoldText is false.
-
-        @param fakeBoldText  setting for kFakeBoldText_Flag
-    */
-    void setFakeBoldText(bool fakeBoldText);
-
-    /** Deprecated.
-    */
-    bool isDevKernText() const { return false; }
-
-    /** Deprecated.
-    */
-    void setDevKernText(bool) { }
+    void setDither(bool dither) { fBitfields.fDither = static_cast<unsigned>(dither); }
 
     /** Returns SkFilterQuality, the image filtering level. A lower setting
         draws faster; a higher setting looks better when the image is scaled.
 
         @return  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
                  kMedium_SkFilterQuality, kHigh_SkFilterQuality
     */
     SkFilterQuality getFilterQuality() const {
@@ -465,17 +195,17 @@ public:
     /** \enum SkPaint::Style
         Set Style to fill, stroke, or both fill and stroke geometry.
         The stroke and fill
         share all paint attributes; for instance, they are drawn with the same color.
 
         Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
         a fill draw.
     */
-    enum Style {
+    enum Style : uint8_t {
         kFill_Style,          //!< set to fill geometry
         kStroke_Style,        //!< set to stroke geometry
         kStrokeAndFill_Style, //!< sets to stroke and fill geometry
     };
 
     /** May be used to verify that SkPaint::Style is a legal value.
     */
     static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
@@ -496,17 +226,17 @@ public:
     /** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits.
         Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract
         a color component.
 
         @return  unpremultiplied ARGB
     */
     SkColor getColor() const { return fColor4f.toSkColor(); }
 
-    /** Retrieves alpha and RGB, unpmreultiplied, as four floating point values. RGB are
+    /** Retrieves alpha and RGB, unpremultiplied, as four floating point values. RGB are
         are extended sRGB values (sRGB gamut, and encoded with the sRGB transfer function).
 
         @return  unpremultiplied RGBA
     */
     SkColor4f getColor4f() const { return fColor4f; }
 
     /** Sets alpha and RGB used when stroking and filling. The color is a 32-bit value,
         unpremultiplied, packing 8-bit components for alpha, red, blue, and green.
@@ -524,27 +254,35 @@ public:
         @param colorSpace  SkColorSpace describing the encoding of color
     */
     void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace);
 
     /** Retrieves alpha from the color used when stroking and filling.
 
         @return  alpha ranging from zero, fully transparent, to 255, fully opaque
     */
-    uint8_t getAlpha() const { return sk_float_round2int(fColor4f.fA * 255); }
+    float getAlphaf() const { return fColor4f.fA; }
+
+    // Helper that scales the alpha by 255.
+    uint8_t getAlpha() const { return sk_float_round2int(this->getAlphaf() * 255); }
 
     /** Replaces alpha, leaving RGB
         unchanged. An out of range value triggers an assert in the debug
-        build. a is a value from zero to 255.
-        a set to zero makes color fully transparent; a set to 255 makes color
+        build. a is a value from 0.0 to 1.0.
+        a set to zero makes color fully transparent; a set to 1.0 makes color
         fully opaque.
 
         @param a  alpha component of color
     */
-    void setAlpha(U8CPU a);
+    void setAlphaf(float a);
+
+    // Helper that accepts an int between 0 and 255, and divides it by 255.0
+    void setAlpha(U8CPU a) {
+        this->setAlphaf(a * (1.0f / 255));
+    }
 
     /** Sets color used when drawing solid fills. The color components range from 0 to 255.
         The color is unpremultiplied; alpha sets the transparency independent of RGB.
 
         @param a  amount of alpha, from fully transparent (0) to fully opaque (255)
         @param r  amount of red, from no red (0) to full red (255)
         @param g  amount of green, from no green (0) to full green (255)
         @param b  amount of blue, from no blue (0) to full blue (255)
@@ -603,17 +341,17 @@ public:
         Choose miter join to draw sharp corners. Choose round join to draw a circle with a
         radius equal to the stroke width on top of the corner. Choose bevel join to minimally
         connect the thick strokes.
 
         The fill path constructed to describe the stroked path respects the join setting but may
         not contain the actual join. For instance, a fill path constructed with round joins does
         not necessarily include circles at each connected segment.
     */
-    enum Join {
+    enum Join : uint8_t {
         kMiter_Join,                 //!< extends to miter limit
         kRound_Join,                 //!< adds circle
         kBevel_Join,                 //!< connects outside edges
         kLast_Join    = kBevel_Join, //!< equivalent to the largest value for Join
         kDefault_Join = kMiter_Join, //!< equivalent to kMiter_Join
     };
 
     /** May be used to verify that SkPaint::Join is a legal value.
@@ -646,17 +384,17 @@ public:
     */
     void setStrokeJoin(Join join);
 
     /** Returns the filled equivalent of the stroked path.
 
         @param src       SkPath read to create a filled version
         @param dst       resulting SkPath; may be the same as src, but may not be nullptr
         @param cullRect  optional limit passed to SkPathEffect
-        @param resScale  if > 1, increase precision, else if (0 < res < 1) reduce precision
+        @param resScale  if > 1, increase precision, else if (0 < resScale < 1) reduce precision
                          to favor speed and size
         @return          true if the path represents style fill, or false if it represents hairline
     */
     bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
                      SkScalar resScale = 1) const;
 
     /** Returns the filled equivalent of the stroked path.
 
@@ -719,30 +457,30 @@ public:
     */
     void setColorFilter(sk_sp<SkColorFilter> colorFilter);
 
     /** Returns SkBlendMode.
         By default, returns SkBlendMode::kSrcOver.
 
         @return  mode used to combine source color with destination color
     */
-    SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }
+    SkBlendMode getBlendMode() const { return (SkBlendMode)fBitfields.fBlendMode; }
 
     /** Returns true if SkBlendMode is SkBlendMode::kSrcOver, the default.
 
         @return  true if SkBlendMode is SkBlendMode::kSrcOver
     */
-    bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }
+    bool isSrcOver() const { return (SkBlendMode)fBitfields.fBlendMode == SkBlendMode::kSrcOver; }
 
     /** Sets SkBlendMode to mode.
         Does not check for valid input.
 
         @param mode  SkBlendMode used to combine source color and destination
     */
-    void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }
+    void setBlendMode(SkBlendMode mode) { fBitfields.fBlendMode = (unsigned)mode; }
 
     /** Returns SkPathEffect if set, or nullptr.
         Does not alter SkPathEffect SkRefCnt.
 
         @return  SkPathEffect if previously set, nullptr otherwise
     */
     SkPathEffect* getPathEffect() const { return fPathEffect.get(); }
 
@@ -782,37 +520,16 @@ public:
         mask alpha unaltered.
 
         Increments maskFilter SkRefCnt by one.
 
         @param maskFilter  modifies clipping mask generated from drawn geometry
     */
     void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);
 
-    /** Returns SkTypeface if set, or nullptr.
-        Does not alter SkTypeface SkRefCnt.
-
-        @return  SkTypeface if previously set, nullptr otherwise
-    */
-    SkTypeface* getTypeface() const { return fTypeface.get(); }
-
-    /** Increases SkTypeface SkRefCnt by one.
-
-        @return  SkTypeface if previously set, nullptr otherwise
-    */
-    sk_sp<SkTypeface> refTypeface() const;
-
-    /** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
-        Pass nullptr to clear SkTypeface and use the default typeface. Increments
-        typeface SkRefCnt by one.
-
-        @param typeface  font and style used to draw text
-    */
-    void setTypeface(sk_sp<SkTypeface> typeface);
-
     /** Returns SkImageFilter if set, or nullptr.
         Does not alter SkImageFilter SkRefCnt.
 
         @return  SkImageFilter if previously set, nullptr otherwise
     */
     SkImageFilter* getImageFilter() const { return fImageFilter.get(); }
 
     /** Returns SkImageFilter if set, or nullptr.
@@ -861,542 +578,16 @@ public:
     */
     void setDrawLooper(sk_sp<SkDrawLooper> drawLooper);
 
     /** Deprecated.
         (see skbug.com/6259)
     */
     void setLooper(sk_sp<SkDrawLooper> drawLooper);
 
-    /** \enum SkPaint::Align
-        Align adjusts the text relative to the text position.
-        Align affects glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
-        SkCanvas::drawPosTextH, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
-        and SkCanvas::drawString;
-        as well as calls that place text glyphs like getTextWidths() and getTextPath().
-
-        The text position is set by the font for both horizontal and vertical text.
-        Typically, for horizontal text, the position is to the left side of the glyph on the
-        base line; and for vertical text, the position is the horizontal center of the glyph
-        at the caps height.
-
-        Align adjusts the glyph position to center it or move it to abut the position
-        using the metrics returned by the font.
-
-        Align defaults to kLeft_Align.
-    */
-    enum Align {
-        kLeft_Align,   //!< positions glyph by computed font offset
-        kCenter_Align, //!< centers line of glyphs by its width or height
-        kRight_Align,  //!< moves lines of glyphs by its width or height
-    };
-
-    /** May be used to verify that align is a legal value.
-    */
-    static constexpr int kAlignCount = 3;
-
-    /** Returns SkPaint::Align.
-        Returns kLeft_Align if SkPaint::Align has not been set.
-
-        @return  text placement relative to position
-    */
-    Align   getTextAlign() const { return (Align)fBitfields.fTextAlign; }
-
-    /** Sets SkPaint::Align to align.
-        Has no effect if align is an invalid value.
-
-        @param align  text placement relative to position
-    */
-    void    setTextAlign(Align align);
-
-    /** Returns text size in points.
-
-        @return  typographic height of text
-    */
-    SkScalar getTextSize() const { return fTextSize; }
-
-    /** Sets text size in points.
-        Has no effect if textSize is not greater than or equal to zero.
-
-        @param textSize  typographic height of text
-    */
-    void setTextSize(SkScalar textSize);
-
-    /** Returns text scale x.
-        Default value is 1.
-
-        @return  text horizontal scale
-    */
-    SkScalar getTextScaleX() const { return fTextScaleX; }
-
-    /** Sets text scale x.
-        Default value is 1.
-
-        @param scaleX  text horizontal scale
-    */
-    void setTextScaleX(SkScalar scaleX);
-
-    /** Returns text skew x.
-        Default value is zero.
-
-        @return  additional shear in x-axis relative to y-axis
-    */
-    SkScalar getTextSkewX() const { return fTextSkewX; }
-
-    /** Sets text skew x.
-        Default value is zero.
-
-        @param skewX  additional shear in x-axis relative to y-axis
-    */
-    void setTextSkewX(SkScalar skewX);
-
-    /** \enum SkPaint::TextEncoding
-        TextEncoding determines whether text specifies character codes and their encoded
-        size, or glyph indices. Characters are encoded as specified by the Unicode standard.
-
-        Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
-        All character code formats are able to represent all of Unicode, differing only
-        in the total storage required.
-
-        UTF-8 (RFC 3629) encodes each character as one or more 8-bit bytes.
-
-        UTF-16 (RFC 2781) encodes each character as one or two 16-bit words.
-
-        UTF-32 encodes each character as one 32-bit word.
-
-        font manager uses font data to convert character code points into glyph indices.
-        A glyph index is a 16-bit word.
-
-        TextEncoding is set to kUTF8_TextEncoding by default.
-    */
-    enum TextEncoding {
-        kUTF8_TextEncoding,    //!< uses bytes to represent UTF-8 or ASCII
-        kUTF16_TextEncoding,   //!< uses two byte words to represent most of Unicode
-        kUTF32_TextEncoding,   //!< uses four byte words to represent all of Unicode
-        kGlyphID_TextEncoding, //!< uses two byte words to represent glyph indices
-    };
-
-    /** Returns SkPaint::TextEncoding.
-        SkPaint::TextEncoding determines how character code points are mapped to font glyph indices.
-
-        @return  one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
-                 kGlyphID_TextEncoding
-    */
-    TextEncoding getTextEncoding() const {
-      return (TextEncoding)fBitfields.fTextEncoding;
-    }
-
-    /** Sets SkPaint::TextEncoding to encoding.
-        SkPaint::TextEncoding determines how character code points are mapped to font glyph indices.
-        Invalid values for encoding are ignored.
-
-        @param encoding  one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
-                         kGlyphID_TextEncoding
-    */
-    void setTextEncoding(TextEncoding encoding);
-
-    /** \struct SkPaint::FontMetrics
-        FontMetrics is filled out by getFontMetrics(). FontMetrics contents reflect the values
-        computed by font manager using SkTypeface. Values are set to zero if they are
-        not available.
-
-        All vertical values are relative to the baseline, on a y-axis pointing down.
-        Zero is on the baseline, negative values are above the baseline, and positive
-        values are below the baseline.
-
-        fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
-        are valid, since their value may be zero.
-
-        fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
-        are valid, since their value may be zero.
-    */
-    struct FontMetrics {
-
-        /** \enum SkPaint::FontMetrics::FontMetricsFlags
-            FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
-            the underline or strikeout metric may be valid and zero.
-            Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
-        */
-        enum FontMetricsFlags {
-            kUnderlineThicknessIsValid_Flag = 1 << 0, //!< set if fUnderlineThickness is valid
-            kUnderlinePositionIsValid_Flag  = 1 << 1, //!< set if fUnderlinePosition is valid
-            kStrikeoutThicknessIsValid_Flag = 1 << 2, //!< set if fStrikeoutThickness is valid
-            kStrikeoutPositionIsValid_Flag  = 1 << 3, //!< set if fStrikeoutPosition is valid
-        };
-
-        uint32_t fFlags;              //!< is set to FontMetricsFlags when metrics are valid
-        SkScalar fTop;                //!< extent above baseline
-        SkScalar fAscent;             //!< distance to reserve above baseline
-        SkScalar fDescent;            //!< distance to reserve below baseline
-        SkScalar fBottom;             //!< extent below baseline
-        SkScalar fLeading;            //!< distance to add between lines
-        SkScalar fAvgCharWidth;       //!< average character width
-        SkScalar fMaxCharWidth;       //!< maximum character width
-        SkScalar fXMin;               //!< minimum x
-        SkScalar fXMax;               //!< maximum x
-        SkScalar fXHeight;            //!< height of lower-case 'x'
-        SkScalar fCapHeight;          //!< height of an upper-case letter
-        SkScalar fUnderlineThickness; //!< underline thickness
-        SkScalar fUnderlinePosition;  //!< underline position relative to baseline
-        SkScalar fStrikeoutThickness; //!< strikeout thickness
-        SkScalar fStrikeoutPosition;  //!< strikeout position relative to baseline
-
-        /** Returns true if SkPaint::FontMetrics has a valid underline thickness, and sets
-            thickness to that value. If the underline thickness is not valid,
-            return false, and ignore thickness.
-
-            @param thickness  storage for underline width
-            @return           true if font specifies underline width
-        */
-        bool hasUnderlineThickness(SkScalar* thickness) const {
-            if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {
-                *thickness = fUnderlineThickness;
-                return true;
-            }
-            return false;
-        }
-
-        /** Returns true if SkPaint::FontMetrics has a valid underline position, and sets
-            position to that value. If the underline position is not valid,
-            return false, and ignore position.
-
-            @param position  storage for underline position
-            @return          true if font specifies underline position
-        */
-        bool hasUnderlinePosition(SkScalar* position) const {
-            if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
-                *position = fUnderlinePosition;
-                return true;
-            }
-            return false;
-        }
-
-        /** Returns true if SkPaint::FontMetrics has a valid strikeout thickness, and sets
-            thickness to that value. If the underline thickness is not valid,
-            return false, and ignore thickness.
-
-            @param thickness  storage for strikeout width
-            @return           true if font specifies strikeout width
-        */
-        bool hasStrikeoutThickness(SkScalar* thickness) const {
-            if (SkToBool(fFlags & kStrikeoutThicknessIsValid_Flag)) {
-                *thickness = fStrikeoutThickness;
-                return true;
-            }
-            return false;
-        }
-
-        /** Returns true if SkPaint::FontMetrics has a valid strikeout position, and sets
-            position to that value. If the underline position is not valid,
-            return false, and ignore position.
-
-            @param position  storage for strikeout position
-            @return          true if font specifies strikeout position
-        */
-        bool hasStrikeoutPosition(SkScalar* position) const {
-            if (SkToBool(fFlags & kStrikeoutPositionIsValid_Flag)) {
-                *position = fStrikeoutPosition;
-                return true;
-            }
-            return false;
-        }
-
-    };
-
-    /** Returns SkPaint::FontMetrics associated with SkTypeface.
-        The return value is the recommended spacing between lines: the sum of metrics
-        descent, ascent, and leading.
-        If metrics is not nullptr, SkPaint::FontMetrics is copied to metrics.
-        Results are scaled by text size but does not take into account
-        dimensions required by text scale x, text skew x, fake bold,
-        style stroke, and SkPathEffect.
-        Results can be additionally scaled by scale; a scale of zero
-        is ignored.
-
-        @param metrics  storage for SkPaint::FontMetrics from SkTypeface; may be nullptr
-        @param scale    additional multiplier for returned values
-        @return         recommended spacing between lines
-    */
-    SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;
-
-    /** Returns the recommended spacing between lines: the sum of metrics
-        descent, ascent, and leading.
-        Result is scaled by text size but does not take into account
-        dimensions required by stroking and SkPathEffect.
-        Returns the same result as getFontMetrics().
-
-        @return  recommended spacing between lines
-    */
-    SkScalar getFontSpacing() const { return this->getFontMetrics(nullptr, 0); }
-
-    /** Converts text into glyph indices.
-        Returns the number of glyph indices represented by text.
-        SkPaint::TextEncoding specifies how text represents characters or glyphs.
-        glyphs may be nullptr, to compute the glyph count.
-
-        Does not check text for valid character codes or valid glyph indices.
-
-        If byteLength equals zero, returns zero.
-        If byteLength includes a partial character, the partial character is ignored.
-
-        If SkPaint::TextEncoding is kUTF8_TextEncoding and
-        text contains an invalid UTF-8 sequence, zero is returned.
-
-        @param text        character storage encoded with SkPaint::TextEncoding
-        @param byteLength  length of character storage in bytes
-        @param glyphs      storage for glyph indices; may be nullptr
-        @return            number of glyphs represented by text of length byteLength
-    */
-    int textToGlyphs(const void* text, size_t byteLength,
-                     SkGlyphID glyphs[]) const;
-
-    /** Returns true if all text corresponds to a non-zero glyph index.
-        Returns false if any characters in text are not supported in
-        SkTypeface.
-
-        If SkPaint::TextEncoding is kGlyphID_TextEncoding,
-        returns true if all glyph indices in text are non-zero;
-        does not check to see if text contains valid glyph indices for SkTypeface.
-
-        Returns true if byteLength is zero.
-
-        @param text        array of characters or glyphs
-        @param byteLength  number of bytes in text array
-        @return            true if all text corresponds to a non-zero glyph index
-    */
-    bool containsText(const void* text, size_t byteLength) const;
-
-    /** Converts glyphs into text if possible.
-        Glyph values without direct Unicode equivalents are mapped to zero.
-        Uses the SkTypeface, but is unaffected
-        by SkPaint::TextEncoding; the text values returned are equivalent to kUTF32_TextEncoding.
-
-        Only supported on platforms that use FreeType as the font engine.
-
-        @param glyphs  array of indices into font
-        @param count   length of glyph array
-        @param text    storage for character codes, one per glyph
-    */
-    void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;
-
-    /** Returns the number of glyphs in text.
-        Uses SkPaint::TextEncoding to count the glyphs.
-        Returns the same result as textToGlyphs().
-
-        @param text        character storage encoded with SkPaint::TextEncoding
-        @param byteLength  length of character storage in bytes
-        @return            number of glyphs represented by text of length byteLength
-    */
-    int countText(const void* text, size_t byteLength) const;
-
-    /** Returns the advance width of text if kVerticalText_Flag is clear,
-        and the height of text if kVerticalText_Flag is set.
-        The advance is the normal distance to move before drawing additional text.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
-        and text size, text scale x, text skew x, stroke width, and
-        SkPathEffect to scale the metrics and bounds.
-        Returns the bounding box of text if bounds is not nullptr.
-        The bounding box is computed as if the text was drawn at the origin.
-
-        @param text    character codes or glyph indices to be measured
-        @param length  number of bytes of text to measure
-        @param bounds  returns bounding box relative to (0, 0) if not nullptr
-        @return        advance width or height
-    */
-    SkScalar measureText(const void* text, size_t length, SkRect* bounds) const;
-
-    /** Returns the advance width of text if kVerticalText_Flag is clear,
-        and the height of text if kVerticalText_Flag is set.
-        The advance is the normal distance to move before drawing additional text.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
-        and text size to scale the metrics.
-        Does not scale the advance or bounds by fake bold or SkPathEffect.
-
-        @param text    character codes or glyph indices to be measured
-        @param length  number of bytes of text to measure
-        @return        advance width or height
-    */
-    SkScalar measureText(const void* text, size_t length) const {
-        return this->measureText(text, length, nullptr);
-    }
-
-    /** Returns the bytes of text that fit within maxWidth.
-        If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
-        equal to maxWidth.
-        If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
-        equal to maxWidth.
-        Measures only while the advance is less than or equal to maxWidth.
-        Returns the advance or the text fragment in measuredWidth if it not nullptr.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
-        and text size to scale the metrics.
-        Does not scale the advance or bounds by fake bold or SkPathEffect.
-
-        @param text           character codes or glyph indices to be measured
-        @param length         number of bytes of text to measure
-        @param maxWidth       advance limit; text is measured while advance is less than maxWidth
-        @param measuredWidth  returns the width of the text less than or equal to maxWidth
-        @return               bytes of text that fit, always less than or equal to length
-    */
-    size_t  breakText(const void* text, size_t length, SkScalar maxWidth,
-                      SkScalar* measuredWidth = nullptr) const;
-
-    /** Retrieves the advance and bounds for each glyph in text, and returns
-        the glyph count in text.
-        Both widths and bounds may be nullptr.
-        If widths is not nullptr, widths must be an array of glyph count entries.
-        if bounds is not nullptr, bounds must be an array of glyph count entries.
-        If kVerticalText_Flag is clear, widths returns the horizontal advance.
-        If kVerticalText_Flag is set, widths returns the vertical advance.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
-        and text size to scale the widths and bounds.
-        Does not scale the advance by fake bold or SkPathEffect.
-        Does include fake bold and SkPathEffect in the bounds.
-
-        @param text        character codes or glyph indices to be measured
-        @param byteLength  number of bytes of text to measure
-        @param widths      returns text advances for each glyph; may be nullptr
-        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
-        @return            glyph count in text
-    */
-    int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
-                      SkRect bounds[] = nullptr) const;
-
-    /** Returns the geometry as SkPath equivalent to the drawn text.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
-        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
-        All of the glyph paths are stored in path.
-        Uses x, y, and SkPaint::Align to position path.
-
-        @param text    character codes or glyph indices
-        @param length  number of bytes of text
-        @param x       x-axis value of the origin of the text
-        @param y       y-axis value of the origin of the text
-        @param path    geometry of the glyphs
-    */
-    void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
-                     SkPath* path) const;
-
-    /** Returns the geometry as SkPath equivalent to the drawn text.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
-        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
-        All of the glyph paths are stored in path.
-        Uses pos array and SkPaint::Align to position path.
-        pos contains a position for each glyph.
-
-        @param text    character codes or glyph indices
-        @param length  number of bytes of text
-        @param pos     positions of each glyph
-        @param path    geometry of the glyphs
-    */
-    void getPosTextPath(const void* text, size_t length,
-                        const SkPoint pos[], SkPath* path) const;
-
-    /** Returns the number of intervals that intersect bounds.
-        bounds describes a pair of lines parallel to the text advance.
-        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
-        the string.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
-        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
-        Uses x, y, and SkPaint::Align to position intervals.
-
-        Pass nullptr for intervals to determine the size of the interval array.
-
-        intervals are cached to improve performance for multiple calls.
-
-        @param text       character codes or glyph indices
-        @param length     number of bytes of text
-        @param x          x-axis value of the origin of the text
-        @param y          y-axis value of the origin of the text
-        @param bounds     lower and upper line parallel to the advance
-        @param intervals  returned intersections; may be nullptr
-        @return           number of intersections; may be zero
-    */
-    int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
-                          const SkScalar bounds[2], SkScalar* intervals) const;
-
-    /** Returns the number of intervals that intersect bounds.
-        bounds describes a pair of lines parallel to the text advance.
-        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
-        the string.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
-        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
-        Uses pos array and SkPaint::Align to position intervals.
-
-        Pass nullptr for intervals to determine the size of the interval array.
-
-        intervals are cached to improve performance for multiple calls.
-
-        @param text       character codes or glyph indices
-        @param length     number of bytes of text
-        @param pos        positions of each glyph
-        @param bounds     lower and upper line parallel to the advance
-        @param intervals  returned intersections; may be nullptr
-        @return           number of intersections; may be zero
-    */
-    int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
-                             const SkScalar bounds[2], SkScalar* intervals) const;
-
-    /** Returns the number of intervals that intersect bounds.
-        bounds describes a pair of lines parallel to the text advance.
-        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
-        the string.
-        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
-        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
-        Uses xpos array, constY, and SkPaint::Align to position intervals.
-
-        Pass nullptr for intervals to determine the size of the interval array.
-
-        intervals are cached to improve performance for multiple calls.
-
-        @param text       character codes or glyph indices
-        @param length     number of bytes of text
-        @param xpos       positions of each glyph in x
-        @param constY     position of each glyph in y
-        @param bounds     lower and upper line parallel to the advance
-        @param intervals  returned intersections; may be nullptr
-        @return           number of intersections; may be zero
-    */
-    int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
-                              SkScalar constY, const SkScalar bounds[2], SkScalar* intervals) const;
-
-    /** Returns the number of intervals that intersect bounds.
-        bounds describes a pair of lines parallel to the text advance.
-        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
-        the string.
-        Uses SkTypeface to get the glyph paths,
-        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
-        Uses run array and SkPaint::Align to position intervals.
-
-        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.
-
-        Pass nullptr for intervals to determine the size of the interval array.
-
-        intervals are cached to improve performance for multiple calls.
-
-        @param blob       glyphs, positions, and text paint attributes
-        @param bounds     lower and upper line parallel to the advance
-        @param intervals  returned intersections; may be nullptr
-        @return           number of intersections; may be zero
-    */
-    int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
-                              SkScalar* intervals) const;
-
-    /** Returns the union of bounds of all glyphs.
-        Returned dimensions are computed by font manager from font data,
-        ignoring SkPaint::Hinting. Includes text size, text scale x,
-        and text skew x, but not fake bold or SkPathEffect.
-
-        If text size is large, text scale x is one, and text skew x is zero,
-        returns the same bounds as SkPaint::FontMetrics { FontMetrics::fXMin,
-        FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
-
-        @return  union of bounds of all glyphs
-    */
-    SkRect getFontBounds() const;
-
     /** Returns true if SkPaint prevents all drawing;
         otherwise, the SkPaint may or may not allow drawing.
 
         Returns true if, for example, SkBlendMode combined with alpha computes a
         new alpha of zero.
 
         @return  true if SkPaint prevents all drawing
     */
@@ -1473,99 +664,34 @@ public:
         @param storage  computed bounds of geometry
         @param style    overrides SkPaint::Style
         @return         fast computed bounds
     */
     const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
                                       Style style) const;
 
 private:
-    friend class SkGlyphRun;
-    friend class SkGlyphRunBuilder;
-    SkPaint(const SkPaint&, const SkRunFont&);
-    typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**, const char*);
-
-    sk_sp<SkTypeface>     fTypeface;
     sk_sp<SkPathEffect>   fPathEffect;
     sk_sp<SkShader>       fShader;
     sk_sp<SkMaskFilter>   fMaskFilter;
     sk_sp<SkColorFilter>  fColorFilter;
     sk_sp<SkDrawLooper>   fDrawLooper;
     sk_sp<SkImageFilter>  fImageFilter;
 
-    SkScalar        fTextSize;
-    SkScalar        fTextScaleX;
-    SkScalar        fTextSkewX;
     SkColor4f       fColor4f;
     SkScalar        fWidth;
     SkScalar        fMiterLimit;
-    uint32_t        fBlendMode; // just need 5-6 bits
     union {
         struct {
-            // all of these bitfields should add up to 32
-            unsigned        fFlags : 16;
-            unsigned        fTextAlign : 2;
-            unsigned        fCapType : 2;
-            unsigned        fJoinType : 2;
-            unsigned        fStyle : 2;
-            unsigned        fTextEncoding : 2;  // 3 values
-            unsigned        fHinting : 2;
-            unsigned        fFilterQuality : 2;
-            //unsigned      fFreeBits : 2;
+            unsigned    fAntiAlias : 1;
+            unsigned    fDither : 1;
+            unsigned    fCapType : 2;
+            unsigned    fJoinType : 2;
+            unsigned    fStyle : 2;
+            unsigned    fFilterQuality : 2;
+            unsigned    fBlendMode : 8; // only need 5-6?
+            unsigned    fPadding : 14;  // 14==32-1-1-2-2-2-2-8
         } fBitfields;
         uint32_t fBitfieldsUInt;
     };
-
-    static GlyphCacheProc GetGlyphCacheProc(TextEncoding encoding,
-                                            bool needFullMetrics);
-
-    SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
-                          int* count, SkRect* bounds) const;
-
-    /*
-     * The luminance color is used to determine which Gamma Canonical color to map to.  This is
-     * really only used by backends which want to cache glyph masks, and need some way to know if
-     * they need to generate new masks based off a given color.
-     */
-    SkColor computeLuminanceColor() const;
-
-    /*  This is the size we use when we ask for a glyph's path. We then
-     *  post-transform it as we draw to match the request.
-     *  This is done to try to re-use cache entries for the path.
-     *
-     *  This value is somewhat arbitrary. In theory, it could be 1, since
-     *  we store paths as floats. However, we get the path from the font
-     *  scaler, and it may represent its paths as fixed-point (or 26.6),
-     *  so we shouldn't ask for something too big (might overflow 16.16)
-     *  or too small (underflow 26.6).
-     *
-     *  This value could track kMaxSizeForGlyphCache, assuming the above
-     *  constraints, but since we ask for unhinted paths, the two values
-     *  need not match per-se.
-     */
-    static constexpr int kCanonicalTextSizeForPaths  = 64;
-
-    static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit);
-
-    // Set flags/hinting/textSize up to use for drawing text as paths.
-    // Returns scale factor to restore the original textSize, since will will
-    // have change it to kCanonicalTextSizeForPaths.
-    SkScalar setupForAsPaths();
-
-    static SkScalar MaxCacheSize2(SkScalar maxLimit);
-
-    friend class GrTextBlob;
-    friend class GrTextContext;
-    friend class GrGLPathRendering;
-    friend class GrPathRendering;
-    friend class SkAutoGlyphCacheNoGamma;
-    friend class SkCanonicalizePaint;
-    friend class SkCanvas;
-    friend class SkDraw;
-    friend class SkGlyphRunListPainter;
-    friend class SkPaintPriv;
-    friend class SkPDFDevice;
-    friend class SkScalerContext;  // for computeLuminanceColor()
-    friend class SkTextBaseIter;
-    friend class SkTextBlobCacheDiffCanvas;
 };
 
 #endif
--- a/gfx/skia/skia/include/core/SkPath.h
+++ b/gfx/skia/skia/include/core/SkPath.h
@@ -58,22 +58,22 @@ public:
         Direction also determines how contour is measured. For instance, dashing
         measures along SkPath to determine where to start and stop stroke; Direction
         will change dashed results as it steps clockwise or counterclockwise.
 
         Closed contours like SkRect, SkRRect, circle, and oval added with
         kCW_Direction travel clockwise; the same added with kCCW_Direction
         travel counterclockwise.
     */
-    enum Direction {
+    enum Direction : int {
         kCW_Direction,  //!< contour travels clockwise
         kCCW_Direction, //!< contour travels counterclockwise
     };
 
-    /** Constucts an empty SkPath. By default, SkPath has no verbs, no SkPoint, and no weights.
+    /** Constructs an empty SkPath. By default, SkPath has no verbs, no SkPoint, and no weights.
         SkPath::FillType is set to kWinding_FillType.
 
         @return  empty SkPath
     */
     SkPath();
 
     /** Constructs a copy of an existing path.
         Copy constructor makes two paths identical by value. Internally, path and
@@ -155,23 +155,16 @@ public:
         @param ending  SkPoint array averaged with this SkPoint array
         @param weight  contribution of this SkPoint array, and
                        one minus contribution of ending SkPoint array
         @param out     SkPath replaced by interpolated averages
         @return        true if SkPath contain same number of SkPoint
     */
     bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;
 
-#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
-    /** To be deprecated soon.
-        Only valid for Android framework.
-    */
-    bool unique() const { return fPathRef->unique(); }
-#endif
-
     /** \enum SkPath::FillType
         FillType selects the rule used to fill SkPath. SkPath set to kWinding_FillType
         fills if the sum of contour edges is not zero, where clockwise edges add one, and
         counterclockwise edges subtract one. SkPath set to kEvenOdd_FillType fills if the
         number of contour edges is odd. Each FillType has an inverse variant that
         reverses the rule:
         kInverseWinding_FillType fills where the sum of contour edges is zero;
         kInverseEvenOdd_FillType fills where the number of contour edges is even.
@@ -235,28 +228,29 @@ public:
 
     /** Computes SkPath::Convexity if required, and returns stored value.
         SkPath::Convexity is computed if stored value is kUnknown_Convexity,
         or if SkPath has been altered since SkPath::Convexity was computed or set.
 
         @return  computed or stored SkPath::Convexity
     */
     Convexity getConvexity() const {
-        for (Convexity convexity = fConvexity.load(); kUnknown_Convexity != convexity; ) {
+        Convexity convexity = this->getConvexityOrUnknown();
+        if (convexity != kUnknown_Convexity) {
             return convexity;
         }
         return this->internalGetConvexity();
     }
 
     /** Returns last computed SkPath::Convexity, or kUnknown_Convexity if
         SkPath has been altered since SkPath::Convexity was computed or set.
 
         @return  stored SkPath::Convexity
     */
-    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
+    Convexity getConvexityOrUnknown() const { return fConvexity.load(std::memory_order_relaxed); }
 
     /** Stores convexity so that it is later returned by getConvexity() or getConvexityOrUnknown().
         convexity may differ from getConvexity(), although setting an incorrect value may
         cause incorrect or inefficient drawing.
 
         If convexity is kUnknown_Convexity: getConvexity() will
         compute SkPath::Convexity, and getConvexityOrUnknown() will return kUnknown_Convexity.
 
@@ -284,17 +278,18 @@ public:
 
         bounds is unmodified if oval is not found.
 
         @param bounds  storage for bounding SkRect of oval; may be nullptr
         @return        true if SkPath is recognized as an oval or circle
     */
     bool isOval(SkRect* bounds) const;
 
-    /** Returns true if this path is recognized as a SkRRect (but not an oval/circle or rect).
+    /** Returns true if path is representable as SkRRect.
+        Returns false if path is representable as oval, circle, or SkRect.
 
         rrect receives bounds of SkRRect.
 
         rrect is unmodified if SkRRect is not found.
 
         @param rrect  storage for bounding SkRect of SkRRect; may be nullptr
         @return       true if SkPath contains only SkRRect
     */
@@ -585,18 +580,18 @@ public:
     SkPath& rMoveTo(SkScalar dx, SkScalar dy);
 
     /** Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is
         kClose_Verb, last point is set to (0, 0) before adding line.
 
         lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
         lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array.
 
-        @param x  end of added line in x
-        @param y  end of added line in y
+        @param x  end of added line on x-axis
+        @param y  end of added line on y-axis
         @return   reference to SkPath
     */
     SkPath& lineTo(SkScalar x, SkScalar y);
 
     /** Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is
         kClose_Verb, last point is set to (0, 0) before adding line.
 
         lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
@@ -626,20 +621,20 @@ public:
     /** Adds quad from last point towards (x1, y1), to (x2, y2).
         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
         before adding quad.
 
         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
         then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2)
         to SkPoint array.
 
-        @param x1  control SkPoint of quad in x
-        @param y1  control SkPoint of quad in y
-        @param x2  end SkPoint of quad in x
-        @param y2  end SkPoint of quad in y
+        @param x1  control SkPoint of quad on x-axis
+        @param y1  control SkPoint of quad on y-axis
+        @param x2  end SkPoint of quad on x-axis
+        @param y2  end SkPoint of quad on y-axis
         @return    reference to SkPath
     */
     SkPath& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
 
     /** Adds quad from last point towards SkPoint p1, to SkPoint p2.
         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
         before adding quad.
 
@@ -684,20 +679,20 @@ public:
         and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights.
 
         If w is one, appends kQuad_Verb to verb array, and
         (x1, y1), (x2, y2) to SkPoint array.
 
         If w is not finite, appends kLine_Verb twice to verb array, and
         (x1, y1), (x2, y2) to SkPoint array.
 
-        @param x1  control SkPoint of conic in x
-        @param y1  control SkPoint of conic in y
-        @param x2  end SkPoint of conic in x
-        @param y2  end SkPoint of conic in y
+        @param x1  control SkPoint of conic on x-axis
+        @param y1  control SkPoint of conic on y-axis
+        @param x2  end SkPoint of conic on x-axis
+        @param y2  end SkPoint of conic on y-axis
         @param w   weight of added conic
         @return    reference to SkPath
     */
     SkPath& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                     SkScalar w);
 
     /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w.
         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
@@ -754,22 +749,22 @@ public:
     /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at
         (x3, y3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
         (0, 0) before adding cubic.
 
         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
         then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3)
         to SkPoint array.
 
-        @param x1  first control SkPoint of cubic in x
-        @param y1  first control SkPoint of cubic in y
-        @param x2  second control SkPoint of cubic in x
-        @param y2  second control SkPoint of cubic in y
-        @param x3  end SkPoint of cubic in x
-        @param y3  end SkPoint of cubic in y
+        @param x1  first control SkPoint of cubic on x-axis
+        @param y1  first control SkPoint of cubic on y-axis
+        @param x2  second control SkPoint of cubic on x-axis
+        @param y2  second control SkPoint of cubic on y-axis
+        @param x3  end SkPoint of cubic on x-axis
+        @param y3  end SkPoint of cubic on y-axis
         @return    reference to SkPath
     */
     SkPath& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                     SkScalar x3, SkScalar y3);
 
     /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at
         SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
         (0, 0) before adding cubic.
@@ -794,26 +789,26 @@ public:
 
         Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
         if needed; then appends kCubic_Verb to verb array; and appends cubic
         control and cubic end to SkPoint array.
         Cubic control is last point plus vector (dx1, dy1).
         Cubic end is last point plus vector (dx2, dy2).
         Function name stands for "relative cubic to".
 
-        @param x1  offset from last point to first cubic control on x-axis
-        @param y1  offset from last point to first cubic control on y-axis
-        @param x2  offset from last point to second cubic control on x-axis
-        @param y2  offset from last point to second cubic control on y-axis
-        @param x3  offset from last point to cubic end on x-axis
-        @param y3  offset from last point to cubic end on y-axis
+        @param dx1  offset from last point to first cubic control on x-axis
+        @param dy1  offset from last point to first cubic control on y-axis
+        @param dx2  offset from last point to second cubic control on x-axis
+        @param dy2  offset from last point to second cubic control on y-axis
+        @param dx3  offset from last point to cubic end on x-axis
+        @param dy3  offset from last point to cubic end on y-axis
         @return    reference to SkPath
     */
-    SkPath& rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
-                     SkScalar x3, SkScalar y3);
+    SkPath& rCubicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+                     SkScalar dx3, SkScalar dy3);
 
     /** Appends arc to SkPath. Arc added is part of ellipse
         bounded by oval, from startAngle through sweepAngle. Both startAngle and
         sweepAngle are measured in degrees, where zero degrees is aligned with the
         positive x-axis, and positive sweeps extends arc clockwise.
 
         arcTo() adds line connecting SkPath last SkPoint to initial arc SkPoint if forceMoveTo
         is false and SkPath is not empty. Otherwise, added contour begins with first point
@@ -824,19 +819,28 @@ public:
         @param sweepAngle   sweep, in degrees. Positive is clockwise; treated modulo 360
         @param forceMoveTo  true to start a new contour with arc
         @return             reference to SkPath
     */
     SkPath& arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
 
     /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
         weighted to describe part of circle. Arc is contained by tangent from
-        last SkPath point (x0, y0) to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc
+        last SkPath point to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc
         is part of circle sized to radius, positioned so it touches both tangent lines.
 
+        If last Path Point does not start Arc, arcTo appends connecting Line to Path.
+        The length of Vector from (x1, y1) to (x2, y2) does not affect Arc.
+
+        Arc sweep is always less than 180 degrees. If radius is zero, or if
+        tangents are nearly parallel, arcTo appends Line from last Path Point to (x1, y1).
+
+        arcTo appends at most one Line and one conic.
+        arcTo implements the functionality of PostScript arct and HTML Canvas arcTo.
+
         @param x1      x-axis value common to pair of tangents
         @param y1      y-axis value common to pair of tangents
         @param x2      x-axis value end of second tangent
         @param y2      y-axis value end of second tangent
         @param radius  distance from arc to circle center
         @return        reference to SkPath
     */
     SkPath& arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
@@ -848,17 +852,17 @@ public:
 
         If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.
         The length of vector from p1 to p2 does not affect arc.
 
         Arc sweep is always less than 180 degrees. If radius is zero, or if
         tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.
 
         arcTo() appends at most one line and one conic.
-        arcTo() implements the functionality of PostScript_Arct and HTML_Canvas_ArcTo.
+        arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo.
 
         @param p1      SkPoint common to pair of tangents
         @param p2      end of second tangent
         @param radius  distance from arc to circle center
         @return        reference to SkPath
     */
     SkPath& arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
         return this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
@@ -879,22 +883,22 @@ public:
         clockwise or counterclockwise, and smaller or larger.
 
         Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if
         either radii are zero, or if last SkPath SkPoint equals (x, y). arcTo() scales radii
         (rx, ry) to fit last SkPath SkPoint and (x, y) if both are greater than zero but
         too small.
 
         arcTo() appends up to four conic curves.
-        arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value
-        is opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise,
-        while kCW_Direction  cast to int is zero.
+        arcTo() implements the functionality of SVG arc, although SVG sweep-flag value
+        is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise,
+        while kCW_Direction cast to int is zero.
 
-        @param rx           radius in x before x-axis rotation
-        @param ry           radius in y before x-axis rotation
+        @param rx           radius on x-axis before x-axis rotation
+        @param ry           radius on y-axis before x-axis rotation
         @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
         @param largeArc     chooses smaller or larger arc
         @param sweep        chooses clockwise or counterclockwise arc
         @param x            end of arc
         @param y            end of arc
         @return             reference to SkPath
     */
     SkPath& arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
@@ -902,41 +906,41 @@ public:
 
     /** Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe
         part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves
         from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes:
         clockwise or counterclockwise,
         and smaller or larger.
 
         Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either
-        radii are zero, or if last SkPath SkPoint equals (x, y). arcTo() scales radii r to fit
-        last SkPath SkPoint and xy if both are greater than zero but too small to describe
+        radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to
+        fit last SkPath SkPoint and xy if both are greater than zero but too small to describe
         an arc.
 
         arcTo() appends up to four conic curves.
-        arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is
-        opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while
+        arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is
+        opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while
         kCW_Direction cast to int is zero.
 
         @param r            radii on axes before x-axis rotation
         @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
         @param largeArc     chooses smaller or larger arc
         @param sweep        chooses clockwise or counterclockwise arc
         @param xy           end of arc
         @return             reference to SkPath
     */
     SkPath& arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
                const SkPoint xy) {
         return this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
     }
 
     /** Appends arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or
         more conic, weighted to describe part of oval with radii (rx, ry) rotated by
-        xAxisRotate degrees. Arc curves from last SkPath SkPoint (x0, y0) to end SkPoint:
-        (x0 + dx, y0 + dy), choosing one of four possible routes: clockwise or
+        xAxisRotate degrees. Arc curves from last SkPath SkPoint to relative end SkPoint:
+        (dx, dy), choosing one of four possible routes: clockwise or
         counterclockwise, and smaller or larger. If SkPath is empty, the start arc SkPoint
         is (0, 0).
 
         Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint
         if either radii are zero, or if last SkPath SkPoint equals end SkPoint.
         arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are
         greater than zero but too small to describe an arc.
 
@@ -1041,18 +1045,18 @@ public:
         @return           true if SkPath contains SkRect
     */
     bool isRect(SkRect* rect, bool* isClosed = nullptr, Direction* direction = nullptr) const;
 
     /** Returns true if SkPath is equivalent to nested SkRect pair when filled.
         If false, rect and dirs are unchanged.
         If true, rect and dirs are written to if not nullptr:
         setting rect[0] to outer SkRect, and rect[1] to inner SkRect;
-        setting dirs[0] to SkPath::Direction of outer SkRect, and dirs[1] to SkPath::Direction of inner
-        SkRect.
+        setting dirs[0] to SkPath::Direction of outer SkRect, and dirs[1] to SkPath::Direction of
+        inner SkRect.
 
         @param rect  storage for SkRect pair; may be nullptr
         @param dirs  storage for SkPath::Direction pair; may be nullptr
         @return      true if SkPath contains nested SkRect pair
     */
     bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = nullptr) const;
 
     /** Adds SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb,
@@ -1153,17 +1157,17 @@ public:
         dir is kCW_Direction, SkRRect starts at top-left of the lower-left corner and
         winds clockwise. If dir is kCCW_Direction, SkRRect starts at the bottom-left
         of the upper-left corner and winds counterclockwise.
 
         If either rx or ry is too large, rx and ry are scaled uniformly until the
         corners fit. If rx or ry is less than or equal to zero, addRoundRect() appends
         SkRect rect to SkPath.
 
-        After appending, SkPath may be empty, or may contain: SkRect, oval, or RoundRect.
+        After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.
 
         @param rect  bounds of SkRRect
         @param rx    x-axis radius of rounded corners on the SkRRect
         @param ry    y-axis radius of rounded corners on the SkRRect
         @param dir   SkPath::Direction to wind SkRRect
         @return      reference to SkPath
     */
     SkPath& addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
@@ -1398,35 +1402,36 @@ public:
     /** \class SkPath::Iter
         Iterates through verb array, and associated SkPoint array and conic weight.
         Provides options to treat open contours as closed, and to ignore
         degenerate data.
     */
     class SK_API Iter {
     public:
 
-        /** Initializes SkPath::Iter with an empty SkPath. next() on SkPath::Iter returns kDone_Verb.
+        /** Initializes SkPath::Iter with an empty SkPath. next() on SkPath::Iter returns
+            kDone_Verb.
             Call setPath to initialize SkPath::Iter at a later time.
 
             @return  SkPath::Iter of empty SkPath
         */
         Iter();
 
-        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.
-            If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
+        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+            path. If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
             open contour. path is not altered.
 
             @param path        SkPath to iterate
             @param forceClose  true if open contours generate kClose_Verb
             @return            SkPath::Iter of path
         */
         Iter(const SkPath& path, bool forceClose);
 
-        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.
-            If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
+        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+            path. If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
             open contour. path is not altered.
 
             @param path        SkPath to iterate
             @param forceClose  true if open contours generate kClose_Verb
         */
         void setPath(const SkPath& path, bool forceClose);
 
         /** Returns next SkPath::Verb in verb array, and advances SkPath::Iter.
@@ -1525,17 +1530,18 @@ public:
 
             @param path  SkPath to iterate
             @return      RawIter of path
         */
         RawIter(const SkPath& path) {
             setPath(path);
         }
 
-        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.
+        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+            path.
 
             @param path  SkPath to iterate
         */
         void setPath(const SkPath& path) {
             fRawIter.setPathRef(*path.fPathRef.get());
         }
 
         /** Returns next SkPath::Verb in verb array, and advances RawIter.
@@ -1646,50 +1652,45 @@ public:
         the format used for SkPath in memory is not guaranteed.
 
         @param buffer  storage for SkPath
         @param length  buffer size in bytes; must be multiple of 4
         @return        number of bytes read, or zero on failure
     */
     size_t readFromMemory(const void* buffer, size_t length);
 
-    /** (see skbug.com/1762)
+    /** (See Skia bug 1762.)
         Returns a non-zero, globally unique value. A different value is returned
         if verb array, SkPoint array, or conic weight changes.
 
-        Setting SkPath::FillType does not change generation id.
+        Setting SkPath::FillType does not change generation identifier.
 
-        Each time the path is modified, a different generation id will be returned.
-        SkPath::FillType does affect generation id on Android framework.
+        Each time the path is modified, a different generation identifier will be returned.
+        SkPath::FillType does affect generation identifier on Android framework.
 
         @return  non-zero, globally unique value
     */
     uint32_t getGenerationID() const;
 
-#ifdef SK_SUPPORT_DIRECT_PATHREF_VALIDATION
     /** Returns if SkPath data is consistent. Corrupt SkPath data is detected if
         internal values are out of range or internal storage does not match
         array dimensions.
 
         @return  true if SkPath data is consistent
     */
     bool isValid() const { return this->isValidImpl() && fPathRef->isValid(); }
-#else
-    bool isValid() const { return this->isValidImpl(); }
-    bool pathRefIsValid() const { return fPathRef->isValid(); }
-#endif
 
 private:
-    sk_sp<SkPathRef>                                     fPathRef;
-    int                                                  fLastMoveToIndex;
-    mutable SkAtomic<Convexity, sk_memory_order_relaxed> fConvexity;       // SkPath::Convexity
-   mutable SkAtomic<uint8_t, sk_memory_order_relaxed> fFirstDirection; // SkPathPriv::FirstDirection
-    uint8_t                                              fFillType    : 2;
-    uint8_t                                              fIsVolatile  : 1;
-    uint8_t                                              fIsBadForDAA : 1;
+    sk_sp<SkPathRef>               fPathRef;
+    int                            fLastMoveToIndex;
+    mutable std::atomic<Convexity> fConvexity;
+    mutable std::atomic<uint8_t>   fFirstDirection; // really an SkPathPriv::FirstDirection
+    uint8_t                        fFillType    : 2;
+    uint8_t                        fIsVolatile  : 1;
+    uint8_t                        fIsBadForDAA : 1;
 
     /** Resets all fields other than fPathRef to their initial 'empty' values.
      *  Assumes the caller has already emptied fPathRef.
      *  On Android increments fGenerationID without reseting it.
      */
     void resetFields();
 
     /** Sets all fields other than fPathRef to the values in 'that'.
@@ -1751,16 +1752,22 @@ private:
     void setBounds(const SkRect& rect) {
         SkPathRef::Editor ed(&fPathRef);
 
         ed.setBounds(rect);
     }
 
     void setPt(int index, SkScalar x, SkScalar y);
 
+    // Bottlenecks for working with fConvexity and fFirstDirection.
+    // Notice the setters are const... these are mutable atomic fields.
+    void    setConvexity(Convexity) const;
+    void    setFirstDirection(uint8_t) const;
+    uint8_t getFirstDirection() const;
+
     friend class SkAutoPathBoundsUpdate;
     friend class SkAutoDisableOvalCheck;
     friend class SkAutoDisableDirectionCheck;
     friend class SkPathWriter;
     friend class SkOpBuilder;
     friend class SkBench_AddPathTest; // perf test reversePathTo
     friend class PathTest_Private; // unit test reversePathTo
     friend class ForceIsRRect_Private; // unit test isRRect
--- a/gfx/skia/skia/include/core/SkPathEffect.h
+++ b/gfx/skia/skia/include/core/SkPathEffect.h
@@ -139,38 +139,33 @@ public:
                                         //   Even values represent ons, and odds offs
         int32_t     fCount;             //!< Number of intervals in the dash. Should be even number
         SkScalar    fPhase;             //!< Offset into the dashed interval pattern
                                         //   mod the sum of all intervals
     };
 
     DashType asADash(DashInfo* info) const;
 
-    static void InitializeFlattenables();
+    static void RegisterFlattenables();
 
     static SkFlattenable::Type GetFlattenableType() {
         return kSkPathEffect_Type;
     }
 
     SkFlattenable::Type getFlattenableType() const override {
         return kSkPathEffect_Type;
     }
 
     static sk_sp<SkPathEffect> Deserialize(const void* data, size_t size,
                                           const SkDeserialProcs* procs = nullptr) {
         return sk_sp<SkPathEffect>(static_cast<SkPathEffect*>(
                                   SkFlattenable::Deserialize(
                                   kSkPathEffect_Type, data, size, procs).release()));
     }
 
-#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
-    /// Override for subclasses as appropriate.
-    virtual bool exposedInAndroidJavaAPI() const { return false; }
-#endif
-
 protected:
     SkPathEffect() {}
 
     virtual bool onFilterPath(SkPath*, const SkPath&, SkStrokeRec*, const SkRect*) const = 0;
     virtual SkRect onComputeFastBounds(const SkRect& src) const {
         return src;
     }
     virtual bool onAsPoints(PointData*, const SkPath&, const SkStrokeRec&, const SkMatrix&,
--- a/gfx/skia/skia/include/core/SkPathMeasure.h
+++ b/gfx/skia/skia/include/core/SkPathMeasure.h
@@ -3,40 +3,36 @@
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkPathMeasure_DEFINED
 #define SkPathMeasure_DEFINED
 
+#include "../private/SkNoncopyable.h"
 #include "../private/SkTDArray.h"
+#include "SkContourMeasure.h"
 #include "SkPath.h"
 
-struct SkConic;
-
 class SK_API SkPathMeasure : SkNoncopyable {
 public:
     SkPathMeasure();
-    /** Initialize the pathmeasure with the specified path. The path must remain valid
-        for the lifetime of the measure object, or until setPath() is called with
-        a different path (or null), since the measure object keeps a pointer to the
-        path object (does not copy its data).
-
-        resScale controls the precision of the measure. values > 1 increase the
-        precision (and possible slow down the computation).
-    */
+    /** Initialize the pathmeasure with the specified path. The parts of the path that are needed
+     *  are copied, so the client is free to modify/delete the path after this call.
+     *
+     *  resScale controls the precision of the measure. values > 1 increase the
+     *  precision (and possible slow down the computation).
+     */
     SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
     ~SkPathMeasure();
 
-    /** Reset the pathmeasure with the specified path. The path must remain valid
-        for the lifetime of the measure object, or until setPath() is called with
-        a different path (or null), since the measure object keeps a pointer to the
-        path object (does not copy its data).
-    */
+    /** Reset the pathmeasure with the specified path. The parts of the path that are needed
+     *  are copied, so the client is free to modify/delete the path after this call..
+     */
     void setPath(const SkPath*, bool forceClosed);
 
     /** Return the total length of the current contour, or 0 if no path
         is associated (e.g. resetPath(null))
     */
     SkScalar getLength();
 
     /** Pins distance to 0 <= distance <= getLength(), and then computes
@@ -78,48 +74,13 @@ public:
     */
     bool nextContour();
 
 #ifdef SK_DEBUG
     void    dump();
 #endif
 
 private:
-    SkPath::Iter    fIter;
-    SkPath          fPath;
-    SkScalar        fTolerance;
-    SkScalar        fLength;            // relative to the current contour
-    unsigned        fFirstPtIndex;      // relative to the current contour
-    bool            fIsClosed;          // relative to the current contour
-    bool            fForceClosed;
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-    int             fSubdivisionsMax;
-#endif
-    struct Segment {
-        SkScalar    fDistance;  // total distance up to this point
-        unsigned    fPtIndex; // index into the fPts array
-        unsigned    fTValue : 30;
-        unsigned    fType : 2;  // actually the enum SkSegType
-                                // See SkPathMeasurePriv.h
-
-        SkScalar getScalarT() const;
-    };
-    SkTDArray<Segment>  fSegments;
-    SkTDArray<SkPoint>  fPts; // Points used to define the segments
-
-    static const Segment* NextSegment(const Segment*);
-
-    void     buildSegments();
-    SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,
-                                int mint, int maxt, unsigned ptIndex);
-    SkScalar compute_conic_segs(const SkConic&, SkScalar distance,
-                                int mint, const SkPoint& minPt,
-                                int maxt, const SkPoint& maxPt, unsigned ptIndex);
-    SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance,
-                                int mint, int maxt, unsigned ptIndex);
-    const Segment* distanceToSegment(SkScalar distance, SkScalar* t);
-    bool quad_too_curvy(const SkPoint pts[3]);
-    bool conic_too_curvy(const SkPoint& firstPt, const SkPoint& midTPt,const SkPoint& lastPt);
-    bool cheap_dist_exceeds_limit(const SkPoint& pt, SkScalar x, SkScalar y);
-    bool cubic_too_curvy(const SkPoint pts[4]);
+    SkContourMeasureIter    fIter;
+    sk_sp<SkContourMeasure> fContour;
 };
 
 #endif
--- a/gfx/skia/skia/include/core/SkPicture.h
+++ b/gfx/skia/skia/include/core/SkPicture.h
@@ -44,35 +44,35 @@ class SkWStream;
 */
 class SK_API SkPicture : public SkRefCnt {
 public:
 
     /** Recreates SkPicture that was serialized into a stream. Returns constructed SkPicture
         if successful; otherwise, returns nullptr. Fails if data does not permit
         constructing valid SkPicture.
 
-        procs.fPictureProc permits supplying a custom function to decode SkPicture.
-        If procs.fPictureProc is nullptr, default decoding is used. procs.fPictureCtx
-        may be used to provide user context to procs.fPictureProc; procs.fPictureProc
+        procs->fPictureProc permits supplying a custom function to decode SkPicture.
+        If procs->fPictureProc is nullptr, default decoding is used. procs->fPictureCtx
+        may be used to provide user context to procs->fPictureProc; procs->fPictureProc
         is called with a pointer to data, data byte length, and user context.
 
         @param stream  container for serial data
         @param procs   custom serial data decoders; may be nullptr
         @return        SkPicture constructed from stream data
     */
     static sk_sp<SkPicture> MakeFromStream(SkStream* stream,
                                            const SkDeserialProcs* procs = nullptr);
 
     /** Recreates SkPicture that was serialized into data. Returns constructed SkPicture
         if successful; otherwise, returns nullptr. Fails if data does not permit
         constructing valid SkPicture.
 
-        procs.fPictureProc permits supplying a custom function to decode SkPicture.
-        If procs.fPictureProc is nullptr, default decoding is used. procs.fPictureCtx
-        may be used to provide user context to procs.fPictureProc; procs.fPictureProc
+        procs->fPictureProc permits supplying a custom function to decode SkPicture.
+        If procs->fPictureProc is nullptr, default decoding is used. procs->fPictureCtx
+        may be used to provide user context to procs->fPictureProc; procs->fPictureProc
         is called with a pointer to data, data byte length, and user context.
 
         @param data   container for serial data
         @param procs  custom serial data decoders; may be nullptr
         @return       SkPicture constructed from data
     */
     static sk_sp<SkPicture> MakeFromData(const SkData* data,
                                          const SkDeserialProcs* procs = nullptr);
@@ -143,36 +143,36 @@ public:
         @return  bounds passed when SkPicture was created
     */
     virtual SkRect cullRect() const = 0;
 
     /** Returns a non-zero value unique among SkPicture in Skia process.
 
         @return  identifier for SkPicture
     */
-    uint32_t uniqueID() const;
+    uint32_t uniqueID() const { return fUniqueID; }
 
     /** Returns storage containing SkData describing SkPicture, using optional custom
         encoders.
 
-        procs.fPictureProc permits supplying a custom function to encode SkPicture.
-        If procs.fPictureProc is nullptr, default encoding is used. procs.fPictureCtx
-        may be used to provide user context to procs.fPictureProc; procs.fPictureProc
+        procs->fPictureProc permits supplying a custom function to encode SkPicture.
+        If procs->fPictureProc is nullptr, default encoding is used. procs->fPictureCtx
+        may be used to provide user context to procs->fPictureProc; procs->fPictureProc
         is called with a pointer to SkPicture and user context.
 
         @param procs  custom serial data encoders; may be nullptr
         @return       storage containing serialized SkPicture
     */
     sk_sp<SkData> serialize(const SkSerialProcs* procs = nullptr) const;
 
     /** Writes picture to stream, using optional custom encoders.
 
-        procs.fPictureProc permits supplying a custom function to encode SkPicture.
-        If procs.fPictureProc is nullptr, default encoding is used. procs.fPictureCtx
-        may be used to provide user context to procs.fPictureProc; procs.fPictureProc
+        procs->fPictureProc permits supplying a custom function to encode SkPicture.
+        If procs->fPictureProc is nullptr, default encoding is used. procs->fPictureCtx
+        may be used to provide user context to procs->fPictureProc; procs->fPictureProc
         is called with a pointer to SkPicture and user context.
 
         @param stream  writable serial data stream
         @param procs   custom serial data encoders; may be nullptr
     */
     void serialize(SkWStream* stream, const SkSerialProcs* procs = nullptr) const;
 
     /** Returns a placeholder SkPicture. Result does not draw, and contains only
@@ -258,27 +258,31 @@ private:
     // V57: Sweep tiling info.
     // V58: No more 2pt conical flipping.
     // V59: No more LocalSpace option on PictureImageFilter
     // V60: Remove flags in picture header
     // V61: Change SkDrawPictureRec to take two colors rather than two alphas
     // V62: Don't negate size of custom encoded images (don't write origin x,y either)
     // V63: Store image bounds (including origin) instead of just width/height to support subsets
     // V64: Remove occluder feature from blur maskFilter
+    // V65: Float4 paint color
+    // V66: Add saveBehind
+    // V67: Blobs serialize fonts instead of paints
+    // V68: Paint doesn't serialize font-related stuff
 
     // Only SKPs within the min/current picture version range (inclusive) can be read.
     static const uint32_t     MIN_PICTURE_VERSION = 56;     // august 2017
-    static const uint32_t CURRENT_PICTURE_VERSION = 65;
+    static const uint32_t CURRENT_PICTURE_VERSION = 68;
 
     static_assert(MIN_PICTURE_VERSION <= 62, "Remove kFontAxes_bad from SkFontDescriptor.cpp");
 
     static bool IsValidPictInfo(const struct SkPictInfo& info);
     static sk_sp<SkPicture> Forwardport(const struct SkPictInfo&,
                                         const class SkPictureData*,
                                         class SkReadBuffer* buffer);
 
     struct SkPictInfo createHeader() const;
     class SkPictureData* backport() const;
 
-    mutable uint32_t fUniqueID;
+    uint32_t fUniqueID;
 };
 
 #endif
--- a/gfx/skia/skia/include/core/SkPixelRef.h
+++ b/gfx/skia/skia/include/core/SkPixelRef.h
@@ -115,21 +115,15 @@ private:
 
     void needsNewGenID();
     void callGenIDChangeListeners();
 
     void setTemporarilyImmutable();
     void restoreMutability();
     friend class SkSurface_Raster;   // For the two methods above.
 
-    friend class SkImage_Raster;
-    friend class SkSpecialImage_Raster;
-
     void setImmutableWithID(uint32_t genID);