Bug 1576041 - Update HarfBuzz to 2.6.1. r=jfkthame
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 23 Aug 2019 14:12:12 +0000
changeset 553346 2643027a3dd8ba3bed25066b0792acc03750ef67
parent 553345 8f0efa5789d0152cdac168adf2d936bc11f68230
child 553347 3db1abb6e436926e67d3dedefeed38fbb1faca01
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1576041
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1576041 - Update HarfBuzz to 2.6.1. r=jfkthame Differential Revision: https://phabricator.services.mozilla.com/D43201
gfx/harfbuzz/NEWS
gfx/harfbuzz/README-mozilla
gfx/harfbuzz/README.md
gfx/harfbuzz/configure.ac
gfx/harfbuzz/src/dev-run.sh
gfx/harfbuzz/src/hb-aat-layout-lcar-table.hh
gfx/harfbuzz/src/hb-aat-layout-opbd-table.hh
gfx/harfbuzz/src/hb-aat-layout-trak-table.hh
gfx/harfbuzz/src/hb-coretext.cc
gfx/harfbuzz/src/hb-directwrite.cc
gfx/harfbuzz/src/hb-directwrite.h
gfx/harfbuzz/src/hb-font.cc
gfx/harfbuzz/src/hb-font.h
gfx/harfbuzz/src/hb-ot-cff2-table.cc
gfx/harfbuzz/src/hb-ot-cmap-table.hh
gfx/harfbuzz/src/hb-ot-layout.cc
gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
gfx/harfbuzz/src/hb-ot-shape-complex-khmer.cc
gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
gfx/harfbuzz/src/hb-ot-shape.cc
gfx/harfbuzz/src/hb-ot-var-avar-table.hh
gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
gfx/harfbuzz/src/hb-version.h
gfx/harfbuzz/update.sh
--- a/gfx/harfbuzz/NEWS
+++ b/gfx/harfbuzz/NEWS
@@ -1,8 +1,19 @@
+Overview of changes leading to 2.6.1
+Thursday, August 22, 2019
+====================================
+- Fix regression with hb_font_create_sub_font scaling introduced in 2.6.0.
+- Change interpretation of font PTEM size / CoreText font size handling.
+  See https://github.com/harfbuzz/harfbuzz/pull/1484
+- hb-ot-font: Prefer symbol cmap subtable if present.
+- Apply 'dist'/'abvm'/'blwm' features to all scripts.
+- Drop experimental DirectWrite API.
+
+
 Overview of changes leading to 2.6.0
 Tuesday, August 13, 2019
 ====================================
 - New OpenType metrics, baseline, and metadata table access APIs.
 - New API to set font variations to a named-instance.
 - New hb-gdi.h header and API for creating hb_face_t from HFONT.
 - Amalgam: Provide a single-file harfbuzz.cc file for easier alternate building.
 - More size-reduction configurable options, enabled by HB_TINY.
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,12 +1,12 @@
 This directory contains the HarfBuzz source from the upstream repo:
 https://github.com/harfbuzz/harfbuzz
 
-Current version: 2.6.0 [commit 6461143b44f81a4190d3f1cb02238750536f08e4]
+Current version: 2.6.1 [commit be97e9d678017d4ec66625fa2b17ef3485552cad]
 
 UPDATING:
 
 Our in-tree copy of HarfBuzz does not depend on any generated files from the
 upstream build system. Therefore, it should be sufficient to simply overwrite
 the in-tree files one the updated ones from upstream to perform updates.
 
 To simplify this, the in-tree copy can be updated by running
--- a/gfx/harfbuzz/README.md
+++ b/gfx/harfbuzz/README.md
@@ -1,11 +1,12 @@
 [![Travis Build Status](https://travis-ci.org/harfbuzz/harfbuzz.svg?branch=master)](https://travis-ci.org/harfbuzz/harfbuzz)
 [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/0t0flrxpstj9lb9w?svg=true&branch=master)](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
 [![CircleCI Build Status](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master)
+[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/harfbuzz.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
 [![Coverity Code Health](https://img.shields.io/coverity/scan/5450.svg)](https://scan.coverity.com/projects/behdad-harfbuzz)
 [![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz)
 [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/master/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
 [![Coverals Code Coverage](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
 [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
 
 This is HarfBuzz, a text shaping library.
 
--- a/gfx/harfbuzz/configure.ac
+++ b/gfx/harfbuzz/configure.ac
@@ -1,11 +1,11 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [2.6.0],
+        [2.6.1],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
 
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
 AC_CONFIG_HEADERS([config.h])
 
deleted file mode 100755
--- a/gfx/harfbuzz/src/dev-run.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/bash
-# Suggested setup to use the script:
-#  (on the root of the project)
-#  $ NOCONFIGURE=1 ./autogen.sh && mkdir build && cd build
-#  $ ../configure --with-freetype --with-glib --with-gobject --with-cairo
-#  $ make -j5 && cd ..
-#  $ src/dev-run.sh [FONT-FILE] [TEXT]
-#
-# Or, using cmake:
-#  $ cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild
-#  $ src/dev-run.sh [FONT-FILE] [TEXT]
-#
-# If you want to open the result rendering using a GUI app,
-#  $ src/dev-run.sh open [FONT-FILE] [TEXT]
-#
-# And if you are using iTerm2, you can use the script like this,
-#  $ src/dev-run.sh img [FONT-FILE] [TEXT]
-#
-
-[ $# = 0 ] && echo Usage: "src/dev-run.sh [FONT-FILE] [TEXT]" && exit
-command -v entr >/dev/null 2>&1 || { echo >&2 "This script needs `entr` be installed"; exit 1; }
-
-
-GDB=gdb
-# if gdb doesn't exist, hopefully lldb exist
-command -v $GDB >/dev/null 2>&1 || export GDB="lldb"
-
-
-[ $1 = "open" ] && openimg=1 && shift
-OPEN=xdg-open
-[ "$(uname)" == "Darwin" ] && OPEN=open
-
-
-[ $1 = "img" ] && img=1 && shift
-# http://iterm2.com/documentation-images.html
-osc="\033]"
-if [[ $TERM == screen* ]]; then osc="\033Ptmux;\033\033]"; fi
-st="\a"
-if [[ $TERM == screen* ]]; then st="\a"; fi
-
-
-tmp=tmp.png
-[ -f 'build/build.ninja' ] && CMAKENINJA=TRUE
-# or "fswatch -0 . -e build/ -e .git"
-find src/ | entr printf '\0' | while read -d ""; do
-	clear
-	yes = | head -n`tput cols` | tr -d '\n'
-	if [[ $CMAKENINJA ]]; then
-		ninja -Cbuild hb-shape hb-view && {
-			build/hb-shape $@
-			if [ $openimg ]; then
-				build/hb-view $@ -O png -o $tmp
-				$OPEN $tmp
-			elif [ $img ]; then
-				build/hb-view $@ -O png -o $tmp
-				printf "\n${osc}1337;File=;inline=1:`cat $tmp | base64`${st}\n"
-			else
-				build/hb-view $@
-			fi
-		}
-	else
-		make -Cbuild/src -j5 -s lib && {
-			build/util/hb-shape $@
-			if [ $openimg ]; then
-				build/util/hb-view $@ -O png -o $tmp
-				$OPEN $tmp
-			elif [ $img ]; then
-				build/util/hb-view $@ -O png -o $tmp
-				printf "\n${osc}1337;File=;inline=1:`cat $tmp | base64`${st}\n"
-			else
-				build/util/hb-view $@
-			fi
-		}
-	fi
-done
-
-read -n 1 -p "[C]heck, [D]ebug, [R]estart, [Q]uit? " answer
-case "$answer" in
-c|C )
-	if [[ $CMAKENINJA ]]; then
-		CTEST_OUTPUT_ON_FAILURE=1 CTEST_PARALLEL_LEVEL=5 ninja -Cbuild test
-	else
-		make -Cbuild -j5 check && .ci/fail.sh
-	fi
-;;
-d|D )
-	if [[ $CMAKENINJA ]]; then
-		echo "Not supported on cmake builds yet"
-	else
-		build/libtool --mode=execute $GDB -- build/util/hb-shape $@
-	fi
-;;
-r|R )
-	src/dev-run.sh $@
-;;
-* )
-	exit
-;;
-esac
--- a/gfx/harfbuzz/src/hb-aat-layout-lcar-table.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout-lcar-table.hh
@@ -33,65 +33,130 @@
  */
 #define HB_AAT_TAG_lcar HB_TAG('l','c','a','r')
 
 
 namespace AAT {
 
 typedef ArrayOf<HBINT16> LigCaretClassEntry;
 
+struct lcarFormat0
+{
+  unsigned int get_lig_carets (hb_font_t      *font,
+			       hb_direction_t  direction,
+			       hb_codepoint_t  glyph,
+			       unsigned int    start_offset,
+			       unsigned int   *caret_count /* IN/OUT */,
+			       hb_position_t  *caret_array /* OUT */,
+			       const void     *base) const
+  {
+    const OffsetTo<LigCaretClassEntry>* entry_offset = lookupTable.get_value (glyph,
+									      font->face->get_num_glyphs ());
+    const LigCaretClassEntry& array = entry_offset ? base+*entry_offset : Null (LigCaretClassEntry);
+    if (caret_count)
+    {
+      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
+      for (unsigned int i = 0; i < arr.length; ++i)
+	caret_array[i] = font->em_scale_dir (arr[i], direction);
+    }
+    return array.len;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  Lookup<OffsetTo<LigCaretClassEntry>>
+		lookupTable;	/* data Lookup table associating glyphs */
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
+struct lcarFormat1
+{
+  unsigned int get_lig_carets (hb_font_t      *font,
+			       hb_direction_t  direction,
+			       hb_codepoint_t  glyph,
+			       unsigned int    start_offset,
+			       unsigned int   *caret_count /* IN/OUT */,
+			       hb_position_t  *caret_array /* OUT */,
+			       const void     *base) const
+  {
+    const OffsetTo<LigCaretClassEntry>* entry_offset = lookupTable.get_value (glyph,
+									      font->face->get_num_glyphs ());
+    const LigCaretClassEntry& array = entry_offset ? base+*entry_offset : Null (LigCaretClassEntry);
+    if (caret_count)
+    {
+      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
+      for (unsigned int i = 0; i < arr.length; ++i)
+      {
+	hb_position_t x = 0, y = 0;
+	font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
+	caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
+      }
+    }
+    return array.len;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  Lookup<OffsetTo<LigCaretClassEntry>>
+		lookupTable;	/* data Lookup table associating glyphs */
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
 struct lcar
 {
   static constexpr hb_tag_t tableTag = HB_AAT_TAG_lcar;
 
   unsigned int get_lig_carets (hb_font_t      *font,
 			       hb_direction_t  direction,
 			       hb_codepoint_t  glyph,
 			       unsigned int    start_offset,
 			       unsigned int   *caret_count /* IN/OUT */,
 			       hb_position_t  *caret_array /* OUT */) const
   {
-    const OffsetTo<LigCaretClassEntry>* entry_offset = lookup.get_value (glyph,
-									 font->face->get_num_glyphs ());
-    const LigCaretClassEntry& array = entry_offset ? this+*entry_offset : Null (LigCaretClassEntry);
-    if (caret_count)
+    switch (format)
     {
-      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
-      switch (format)
-      {
-      case 0:
-	for (unsigned int i = 0; i < arr.length; ++i)
-	  caret_array[i] = font->em_scale_dir (arr[i], direction);
-	break;
-      case 1:
-	for (unsigned int i = 0; i < arr.length; ++i)
-	{
-	  hb_position_t x, y;
-	  font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
-	  caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
-	}
-	break;
-      }
+    case 0: return u.format0.get_lig_carets (font, direction, glyph, start_offset,
+					     caret_count, caret_array, this);
+    case 1: return u.format1.get_lig_carets (font, direction, glyph, start_offset,
+					     caret_count, caret_array, this);
+    default:if (caret_count) *caret_count = 0; return 0;
     }
-    return array.len;
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  version.major == 1 &&
-			  lookup.sanitize (c, this)));
+    if (unlikely (!c->check_struct (this) || version.major != 1))
+      return_trace (false);
+
+    switch (format) {
+    case 0: return_trace (u.format0.sanitize (c, this));
+    case 1: return_trace (u.format1.sanitize (c, this));
+    default:return_trace (true);
+    }
   }
 
   protected:
   FixedVersion<>version;	/* Version number of the ligature caret table */
   HBUINT16	format;		/* Format of the ligature caret table. */
-  Lookup<OffsetTo<LigCaretClassEntry>>
-		lookup;		/* data Lookup table associating glyphs */
-
+  union {
+  lcarFormat0	format0;
+  lcarFormat0	format1;
+  } u;
   public:
   DEFINE_SIZE_MIN (8);
 };
 
 } /* namespace AAT */
 
 #endif /* HB_AAT_LAYOUT_LCAR_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-aat-layout-opbd-table.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout-opbd-table.hh
@@ -40,72 +40,134 @@ namespace AAT {
 struct OpticalBounds
 {
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  HBINT16	leftSide;
-  HBINT16	topSide;
-  HBINT16	rightSide;
-  HBINT16	bottomSide;
+  FWORD		leftSide;
+  FWORD		topSide;
+  FWORD		rightSide;
+  FWORD		bottomSide;
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
+struct opbdFormat0
+{
+  bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
+		   hb_glyph_extents_t *extents, const void *base) const
+  {
+    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
+    if (!bounds_offset) return false;
+    const OpticalBounds &bounds = base+*bounds_offset;
+
+    if (extents)
+      *extents = {
+	font->em_scale_x (bounds.leftSide),
+	font->em_scale_y (bounds.topSide),
+	font->em_scale_x (bounds.rightSide),
+	font->em_scale_y (bounds.bottomSide)
+      };
+    return true;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  Lookup<OffsetTo<OpticalBounds>>
+		lookupTable;	/* Lookup table associating glyphs with the four
+				 * int16 values for the left-side, top-side,
+				 * right-side, and bottom-side optical bounds. */
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
+struct opbdFormat1
+{
+  bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
+		   hb_glyph_extents_t *extents, const void *base) const
+  {
+    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
+    if (!bounds_offset) return false;
+    const OpticalBounds &bounds = base+*bounds_offset;
+
+    hb_position_t left = 0, top = 0, right = 0, bottom = 0, ignore;
+    if (font->get_glyph_contour_point (glyph_id, bounds.leftSide, &left, &ignore) ||
+	font->get_glyph_contour_point (glyph_id, bounds.topSide, &ignore, &top) ||
+	font->get_glyph_contour_point (glyph_id, bounds.rightSide, &right, &ignore) ||
+	font->get_glyph_contour_point (glyph_id, bounds.bottomSide, &ignore, &bottom))
+    {
+      if (extents)
+	*extents = {left, top, right, bottom};
+      return true;
+    }
+    return false;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  Lookup<OffsetTo<OpticalBounds>>
+		lookupTable;	/* Lookup table associating glyphs with the four
+				 * int16 values for the left-side, top-side,
+				 * right-side, and bottom-side optical bounds. */
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
 struct opbd
 {
   static constexpr hb_tag_t tableTag = HB_AAT_TAG_opbd;
 
-  bool get_optical_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
-			   hb_position_t *left, hb_position_t *top,
-			   hb_position_t *right, hb_position_t *bottom) const
+  bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
+		   hb_glyph_extents_t *extents) const
   {
-    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
-    if (!bounds_offset) return false;
-    const OpticalBounds &bounds = this+*bounds_offset;
     switch (format)
     {
-    case 0:
-      *left = font->em_scale_x (bounds.leftSide);
-      *top = font->em_scale_y (bounds.topSide);
-      *right = font->em_scale_x (bounds.rightSide);
-      *bottom = font->em_scale_y (bounds.bottomSide);
-      return true;
-    case 1:
-      hb_position_t ignore;
-      return font->get_glyph_contour_point (glyph_id, bounds.leftSide, left, &ignore) &&
-	     font->get_glyph_contour_point (glyph_id, bounds.topSide, &ignore, top) &&
-	     font->get_glyph_contour_point (glyph_id, bounds.rightSide, right, &ignore) &&
-	     font->get_glyph_contour_point (glyph_id, bounds.bottomSide, &ignore, bottom);
-    default:
-      return false;
+    case 0: return u.format0.get_bounds (font, glyph_id, extents, this);
+    case 1: return u.format1.get_bounds (font, glyph_id, extents, this);
+    default:return false;
     }
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  version.major == 1 &&
-			  lookupTable.sanitize (c, this)));
+    if (unlikely (!c->check_struct (this) || version.major != 1))
+      return_trace (false);
+
+    switch (format)
+    {
+    case 0: return_trace (u.format0.sanitize (c, this));
+    case 1: return_trace (u.format1.sanitize (c, this));
+    default:return_trace (true);
+    }
   }
 
   protected:
   FixedVersion<>version;	/* Version number of the optical bounds
 				 * table (0x00010000 for the current version). */
   HBUINT16	format;		/* Format of the optical bounds table.
 				 * Format 0 indicates distance and Format 1 indicates
 				 * control point. */
-  Lookup<OffsetTo<OpticalBounds>>
-		lookupTable;	/* Lookup table associating glyphs with the four
-				 * int16 values for the left-side, top-side,
-				 * right-side, and bottom-side optical bounds. */
+  union {
+  opbdFormat0 format0;
+  opbdFormat1 format1;
+  } u;
   public:
   DEFINE_SIZE_MIN (8);
 };
 
 } /* namespace AAT */
 
 
 #endif /* HB_AAT_LAYOUT_OPBD_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-aat-layout-trak-table.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout-trak-table.hh
@@ -88,23 +88,16 @@ struct TrackData
     float s1 = size_table[idx + 1].to_float ();
     float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
     return t * trackTableEntry.get_value (base, idx + 1, sizes) +
 	   (1.f - t) * trackTableEntry.get_value (base, idx, sizes);
   }
 
   int get_tracking (const void *base, float ptem) const
   {
-    /* CoreText points are CSS pixels (96 per inch),
-     * NOT typographic points (72 per inch).
-     *
-     * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
-     */
-    float csspx = ptem * 96.f / 72.f;
-
     /*
      * Choose track.
      */
     const TrackTableEntry *trackTableEntry = nullptr;
     unsigned int count = nTracks;
     for (unsigned int i = 0; i < count; i++)
     {
       /* Note: Seems like the track entries are sorted by values.  But the
@@ -125,20 +118,20 @@ struct TrackData
      */
     unsigned int sizes = nSizes;
     if (!sizes) return 0.;
     if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
 
     hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
     unsigned int size_index;
     for (size_index = 0; size_index < sizes - 1; size_index++)
-      if (size_table[size_index].to_float () >= csspx)
+      if (size_table[size_index].to_float () >= ptem)
         break;
 
-    return roundf (interpolate_at (size_index ? size_index - 1 : 0, csspx,
+    return roundf (interpolate_at (size_index ? size_index - 1 : 0, ptem,
 				   *trackTableEntry, base));
   }
 
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
 			  sizeTable.sanitize (c, base, nSizes) &&
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -44,34 +44,16 @@
  * @include: hb-coretext.h
  *
  * Functions for using HarfBuzz with the CoreText fonts.
  **/
 
 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
 
-static CGFloat
-coretext_font_size_from_ptem (float ptem)
-{
-  /* CoreText points are CSS pixels (96 per inch),
-   * NOT typographic points (72 per inch).
-   *
-   * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
-   */
-  ptem *= 96.f / 72.f;
-  return (CGFloat) (ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem);
-}
-static float
-coretext_font_size_to_ptem (CGFloat size)
-{
-  size *= 72. / 96.;
-  return size <= 0 ? 0 : size;
-}
-
 static void
 release_table_data (void *user_data)
 {
   CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
   CFRelease(cf_data);
 }
 
 static hb_blob_t *
@@ -315,17 +297,18 @@ hb_coretext_face_get_cg_font (hb_face_t 
 hb_coretext_font_data_t *
 _hb_coretext_shaper_font_data_create (hb_font_t *font)
 {
   hb_face_t *face = font->face;
   const hb_coretext_face_data_t *face_data = face->data.coretext;
   if (unlikely (!face_data)) return nullptr;
   CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
 
-  CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
+  CGFloat font_size = font->ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : font->ptem;
+  CTFontRef ct_font = create_ct_font (cg_font, font_size);
 
   if (unlikely (!ct_font))
   {
     DEBUG_MSG (CORETEXT, font, "CGFont creation failed..");
     return nullptr;
   }
 
   return (hb_coretext_font_data_t *) ct_font;
@@ -339,17 +322,17 @@ void
 
 static const hb_coretext_font_data_t *
 hb_coretext_font_data_sync (hb_font_t *font)
 {
 retry:
   const hb_coretext_font_data_t *data = font->data.coretext;
   if (unlikely (!data)) return nullptr;
 
-  if (fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) > .5)
+  if (fabs (CTFontGetSize ((CTFontRef) data) - font->ptem) > .5)
   {
     /* XXX-MT-bug
      * Note that evaluating condition above can be dangerous if another thread
      * got here first and destructed data.  That's, as always, bad use pattern.
      * If you modify the font (change font size), other threads must not be
      * using it at the same time.  However, since this check is delayed to
      * when one actually tries to shape something, this is a XXX race condition
      * (and the only one we have that I know of) right now.  Ie. you modify the
@@ -379,17 +362,17 @@ hb_coretext_font_create (CTFontRef ct_fo
   hb_face_t *face = hb_coretext_face_create (cg_font);
   CFRelease (cg_font);
   hb_font_t *font = hb_font_create (face);
   hb_face_destroy (face);
 
   if (unlikely (hb_object_is_immutable (font)))
     return font;
 
-  hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
+  hb_font_set_ptem (font, CTFontGetSize (ct_font));
 
   /* Let there be dragons here... */
   font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
 
   return font;
 }
 
 CTFontRef
--- a/gfx/harfbuzz/src/hb-directwrite.cc
+++ b/gfx/harfbuzz/src/hb-directwrite.cc
@@ -874,39 +874,22 @@ hb_bool_t
 		       hb_buffer_t        *buffer,
 		       const hb_feature_t *features,
 		       unsigned int        num_features)
 {
   return _hb_directwrite_shape_full (shape_plan, font, buffer,
 				     features, num_features, 0);
 }
 
-/**
- * hb_directwrite_shape_experimental_width:
- * Experimental API to test DirectWrite's justification algorithm.
- *
- * It inserts Kashida at wrong order so don't use the API ever.
- *
- * It doesn't work with cygwin/msys due to header bugs so one
- * should use MSVC toolchain in order to use it for now.
- *
- * @font:
- * @buffer:
- * @features:
- * @num_features:
- * @width:
- *
- * Since: 1.4.2
- **/
-hb_bool_t
-hb_directwrite_shape_experimental_width (hb_font_t          *font,
-					 hb_buffer_t        *buffer,
-					 const hb_feature_t *features,
-					 unsigned int        num_features,
-					 float               width)
+HB_UNUSED static bool
+_hb_directwrite_shape_experimental_width (hb_font_t          *font,
+					  hb_buffer_t        *buffer,
+					  const hb_feature_t *features,
+					  unsigned int        num_features,
+					  float               width)
 {
   static const char *shapers = "directwrite";
   hb_shape_plan_t *shape_plan;
   shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
 					    features, num_features, &shapers);
   hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer,
 					      features, num_features, width);
 
--- a/gfx/harfbuzz/src/hb-directwrite.h
+++ b/gfx/harfbuzz/src/hb-directwrite.h
@@ -24,21 +24,16 @@
 
 #ifndef HB_DIRECTWRITE_H
 #define HB_DIRECTWRITE_H
 
 #include "hb.h"
 
 HB_BEGIN_DECLS
 
-HB_EXTERN hb_bool_t
-hb_directwrite_shape_experimental_width (hb_font_t *font, hb_buffer_t *buffer,
-					 const hb_feature_t *features,
-					 unsigned int num_features, float width);
-
 HB_EXTERN hb_face_t *
 hb_directwrite_face_create (IDWriteFontFace *font_face);
 
 HB_EXTERN IDWriteFontFace *
 hb_directwrite_face_get_font_face (hb_face_t *face);
 
 HB_END_DECLS
 
--- a/gfx/harfbuzz/src/hb-font.cc
+++ b/gfx/harfbuzz/src/hb-font.cc
@@ -513,19 +513,19 @@ static const hb_font_funcs_t _hb_font_fu
     }
   }
 };
 
 
 /**
  * hb_font_funcs_create: (Xconstructor)
  *
- * 
+ *
  *
- * Return value: (transfer full): 
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
 hb_font_funcs_create ()
 {
   hb_font_funcs_t *ffuncs;
 
@@ -535,49 +535,49 @@ hb_font_funcs_create ()
   ffuncs->get = _hb_font_funcs_default.get;
 
   return ffuncs;
 }
 
 /**
  * hb_font_funcs_get_empty:
  *
- * 
+ *
  *
- * Return value: (transfer full): 
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
 hb_font_funcs_get_empty ()
 {
   return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_default);
 }
 
 /**
  * hb_font_funcs_reference: (skip)
  * @ffuncs: font functions.
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
 hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
 {
   return hb_object_reference (ffuncs);
 }
 
 /**
  * hb_font_funcs_destroy: (skip)
  * @ffuncs: font functions.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
 {
   if (!hb_object_destroy (ffuncs)) return;
 
@@ -587,80 +587,80 @@ hb_font_funcs_destroy (hb_font_funcs_t *
 #undef HB_FONT_FUNC_IMPLEMENT
 
   free (ffuncs);
 }
 
 /**
  * hb_font_funcs_set_user_data: (skip)
  * @ffuncs: font functions.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
 			     hb_user_data_key_t *key,
 			     void *              data,
 			     hb_destroy_func_t   destroy,
 			     hb_bool_t           replace)
 {
   return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
 }
 
 /**
  * hb_font_funcs_get_user_data: (skip)
  * @ffuncs: font functions.
- * @key: 
+ * @key:
+ *
  *
- * 
  *
- * Return value: (transfer none): 
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
 void *
 hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
 			     hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (ffuncs, key);
 }
 
 
 /**
  * hb_font_funcs_make_immutable:
  * @ffuncs: font functions.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 {
   if (hb_object_is_immutable (ffuncs))
     return;
 
   hb_object_make_immutable (ffuncs);
 }
 
 /**
  * hb_font_funcs_is_immutable:
  * @ffuncs: font functions.
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
 {
   return hb_object_is_immutable (ffuncs);
 }
@@ -746,118 +746,118 @@ hb_font_get_v_extents (hb_font_t *font,
 		       hb_font_extents_t *extents)
 {
   return font->get_font_v_extents (extents);
 }
 
 /**
  * hb_font_get_glyph:
  * @font: a font.
- * @unicode: 
- * @variation_selector: 
- * @glyph: (out): 
+ * @unicode:
+ * @variation_selector:
+ * @glyph: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph (hb_font_t *font,
 		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 		   hb_codepoint_t *glyph)
 {
   if (unlikely (variation_selector))
     return font->get_variation_glyph (unicode, variation_selector, glyph);
   return font->get_nominal_glyph (unicode, glyph);
 }
 
 /**
  * hb_font_get_nominal_glyph:
  * @font: a font.
- * @unicode: 
- * @glyph: (out): 
+ * @unicode:
+ * @glyph: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 1.2.3
  **/
 hb_bool_t
 hb_font_get_nominal_glyph (hb_font_t *font,
 			   hb_codepoint_t unicode,
 			   hb_codepoint_t *glyph)
 {
   return font->get_nominal_glyph (unicode, glyph);
 }
 
 /**
  * hb_font_get_variation_glyph:
  * @font: a font.
- * @unicode: 
- * @variation_selector: 
- * @glyph: (out): 
+ * @unicode:
+ * @variation_selector:
+ * @glyph: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 1.2.3
  **/
 hb_bool_t
 hb_font_get_variation_glyph (hb_font_t *font,
 			     hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 			     hb_codepoint_t *glyph)
 {
   return font->get_variation_glyph (unicode, variation_selector, glyph);
 }
 
 /**
  * hb_font_get_glyph_h_advance:
  * @font: a font.
- * @glyph: 
+ * @glyph:
+ *
  *
- * 
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_position_t
 hb_font_get_glyph_h_advance (hb_font_t *font,
 			     hb_codepoint_t glyph)
 {
   return font->get_glyph_h_advance (glyph);
 }
 
 /**
  * hb_font_get_glyph_v_advance:
  * @font: a font.
- * @glyph: 
+ * @glyph:
+ *
  *
- * 
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_position_t
 hb_font_get_glyph_v_advance (hb_font_t *font,
 			     hb_codepoint_t glyph)
 {
   return font->get_glyph_v_advance (glyph);
 }
 
 /**
  * hb_font_get_glyph_h_advances:
  * @font: a font.
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
 void
 hb_font_get_glyph_h_advances (hb_font_t* font,
 			      unsigned int count,
 			      const hb_codepoint_t *first_glyph,
 			      unsigned glyph_stride,
@@ -865,17 +865,17 @@ hb_font_get_glyph_h_advances (hb_font_t*
 			      unsigned advance_stride)
 {
   font->get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
 }
 /**
  * hb_font_get_glyph_v_advances:
  * @font: a font.
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
 void
 hb_font_get_glyph_v_advances (hb_font_t* font,
 			      unsigned int count,
 			      const hb_codepoint_t *first_glyph,
 			      unsigned glyph_stride,
@@ -883,169 +883,169 @@ hb_font_get_glyph_v_advances (hb_font_t*
 			      unsigned advance_stride)
 {
   font->get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
 }
 
 /**
  * hb_font_get_glyph_h_origin:
  * @font: a font.
- * @glyph: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_h_origin (hb_font_t *font,
 			    hb_codepoint_t glyph,
 			    hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_h_origin (glyph, x, y);
 }
 
 /**
  * hb_font_get_glyph_v_origin:
  * @font: a font.
- * @glyph: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_v_origin (hb_font_t *font,
 			    hb_codepoint_t glyph,
 			    hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_v_origin (glyph, x, y);
 }
 
 /**
  * hb_font_get_glyph_h_kerning:
  * @font: a font.
- * @left_glyph: 
- * @right_glyph: 
+ * @left_glyph:
+ * @right_glyph:
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_position_t
 hb_font_get_glyph_h_kerning (hb_font_t *font,
 			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
 {
   return font->get_glyph_h_kerning (left_glyph, right_glyph);
 }
 
 #ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_font_get_glyph_v_kerning:
  * @font: a font.
- * @top_glyph: 
- * @bottom_glyph: 
+ * @top_glyph:
+ * @bottom_glyph:
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  * Deprecated: 2.0.0
  **/
 hb_position_t
 hb_font_get_glyph_v_kerning (hb_font_t *font,
 			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
 {
   return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
 }
 #endif
 
 /**
  * hb_font_get_glyph_extents:
  * @font: a font.
- * @glyph: 
- * @extents: (out): 
+ * @glyph:
+ * @extents: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_extents (hb_font_t *font,
 			   hb_codepoint_t glyph,
 			   hb_glyph_extents_t *extents)
 {
   return font->get_glyph_extents (glyph, extents);
 }
 
 /**
  * hb_font_get_glyph_contour_point:
  * @font: a font.
- * @glyph: 
- * @point_index: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @point_index:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_contour_point (hb_font_t *font,
 				 hb_codepoint_t glyph, unsigned int point_index,
 				 hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_contour_point (glyph, point_index, x, y);
 }
 
 /**
  * hb_font_get_glyph_name:
  * @font: a font.
- * @glyph: 
- * @name: (array length=size): 
- * @size: 
+ * @glyph:
+ * @name: (array length=size):
+ * @size:
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_name (hb_font_t *font,
 			hb_codepoint_t glyph,
 			char *name, unsigned int size)
 {
   return font->get_glyph_name (glyph, name, size);
 }
 
 /**
  * hb_font_get_glyph_from_name:
  * @font: a font.
- * @name: (array length=len): 
- * @len: 
- * @glyph: (out): 
+ * @name: (array length=len):
+ * @len:
+ * @glyph: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_from_name (hb_font_t *font,
 			     const char *name, int len, /* -1 means nul-terminated */
 			     hb_codepoint_t *glyph)
 {
@@ -1070,39 +1070,39 @@ hb_font_get_extents_for_direction (hb_fo
 				   hb_direction_t direction,
 				   hb_font_extents_t *extents)
 {
   return font->get_extents_for_direction (direction, extents);
 }
 /**
  * hb_font_get_glyph_advance_for_direction:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_get_glyph_advance_for_direction (hb_font_t *font,
 					 hb_codepoint_t glyph,
 					 hb_direction_t direction,
 					 hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
 }
 /**
  * hb_font_get_glyph_advances_for_direction:
  * @font: a font.
- * @direction: 
+ * @direction:
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
 HB_EXTERN void
 hb_font_get_glyph_advances_for_direction (hb_font_t* font,
 					  hb_direction_t direction,
 					  unsigned int count,
 					  const hb_codepoint_t *first_glyph,
@@ -1111,175 +1111,175 @@ hb_font_get_glyph_advances_for_direction
 					  unsigned advance_stride)
 {
   font->get_glyph_advances_for_direction (direction, count, first_glyph, glyph_stride, first_advance, advance_stride);
 }
 
 /**
  * hb_font_get_glyph_origin_for_direction:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
 					hb_codepoint_t glyph,
 					hb_direction_t direction,
 					hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_origin_for_direction (glyph, direction, x, y);
 }
 
 /**
  * hb_font_add_glyph_origin_for_direction:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_add_glyph_origin_for_direction (hb_font_t *font,
 					hb_codepoint_t glyph,
 					hb_direction_t direction,
 					hb_position_t *x, hb_position_t *y)
 {
   return font->add_glyph_origin_for_direction (glyph, direction, x, y);
 }
 
 /**
  * hb_font_subtract_glyph_origin_for_direction:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
 					     hb_codepoint_t glyph,
 					     hb_direction_t direction,
 					     hb_position_t *x, hb_position_t *y)
 {
   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
 }
 
 /**
  * hb_font_get_glyph_kerning_for_direction:
  * @font: a font.
- * @first_glyph: 
- * @second_glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @first_glyph:
+ * @second_glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
 					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
 					 hb_direction_t direction,
 					 hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
 }
 
 /**
  * hb_font_get_glyph_extents_for_origin:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @extents: (out): 
+ * @glyph:
+ * @direction:
+ * @extents: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
 				      hb_codepoint_t glyph,
 				      hb_direction_t direction,
 				      hb_glyph_extents_t *extents)
 {
   return font->get_glyph_extents_for_origin (glyph, direction, extents);
 }
 
 /**
  * hb_font_get_glyph_contour_point_for_origin:
  * @font: a font.
- * @glyph: 
- * @point_index: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @point_index:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
 					    hb_codepoint_t glyph, unsigned int point_index,
 					    hb_direction_t direction,
 					    hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
 }
 
 /* Generates gidDDD if glyph has no name. */
 /**
  * hb_font_glyph_to_string:
  * @font: a font.
- * @glyph: 
- * @s: (array length=size): 
- * @size: 
+ * @glyph:
+ * @s: (array length=size):
+ * @size:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_glyph_to_string (hb_font_t *font,
 			 hb_codepoint_t glyph,
 			 char *s, unsigned int size)
 {
   font->glyph_to_string (glyph, s, size);
 }
 
 /* Parses gidDDD and uniUUUU strings automatically. */
 /**
  * hb_font_glyph_from_string:
  * @font: a font.
- * @s: (array length=len) (element-type uint8_t): 
- * @len: 
- * @glyph: (out): 
+ * @s: (array length=len) (element-type uint8_t):
+ * @len:
+ * @glyph: (out):
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_glyph_from_string (hb_font_t *font,
 			   const char *s, int len, /* -1 means nul-terminated */
 			   hb_codepoint_t *glyph)
 {
@@ -1336,19 +1336,19 @@ static hb_font_t *
 
   return font;
 }
 
 /**
  * hb_font_create: (Xconstructor)
  * @face: a face.
  *
- * 
+ *
  *
- * Return value: (transfer full): 
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_create (hb_face_t *face)
 {
   hb_font_t *font = _hb_font_create (face);
 
@@ -1359,19 +1359,19 @@ hb_font_create (hb_face_t *face)
 
   return font;
 }
 
 /**
  * hb_font_create_sub_font:
  * @parent: parent font.
  *
- * 
+ *
  *
- * Return value: (transfer full): 
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_create_sub_font (hb_font_t *parent)
 {
   if (unlikely (!parent))
     parent = hb_font_get_empty ();
@@ -1380,72 +1380,71 @@ hb_font_create_sub_font (hb_font_t *pare
 
   if (unlikely (hb_object_is_immutable (font)))
     return font;
 
   font->parent = hb_font_reference (parent);
 
   font->x_scale = parent->x_scale;
   font->y_scale = parent->y_scale;
+  font->mults_changed ();
   font->x_ppem = parent->x_ppem;
   font->y_ppem = parent->y_ppem;
   font->ptem = parent->ptem;
 
   font->num_coords = parent->num_coords;
-  if (!font->num_coords)
-    font->coords = nullptr;
-  else
+  if (font->num_coords)
   {
     unsigned int size = parent->num_coords * sizeof (parent->coords[0]);
     font->coords = (int *) malloc (size);
     if (unlikely (!font->coords))
       font->num_coords = 0;
     else
       memcpy (font->coords, parent->coords, size);
   }
 
   return font;
 }
 
 /**
  * hb_font_get_empty:
  *
- * 
+ *
  *
  * Return value: (transfer full)
  *
  * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_get_empty ()
 {
   return const_cast<hb_font_t *> (&Null(hb_font_t));
 }
 
 /**
  * hb_font_reference: (skip)
  * @font: a font.
  *
- * 
+ *
  *
- * Return value: (transfer full): 
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_reference (hb_font_t *font)
 {
   return hb_object_reference (font);
 }
 
 /**
  * hb_font_destroy: (skip)
  * @font: a font.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_destroy (hb_font_t *font)
 {
   if (!hb_object_destroy (font)) return;
 
@@ -1461,60 +1460,60 @@ hb_font_destroy (hb_font_t *font)
   free (font->coords);
 
   free (font);
 }
 
 /**
  * hb_font_set_user_data: (skip)
  * @font: a font.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_set_user_data (hb_font_t          *font,
 		       hb_user_data_key_t *key,
 		       void *              data,
 		       hb_destroy_func_t   destroy,
 		       hb_bool_t           replace)
 {
   return hb_object_set_user_data (font, key, data, destroy, replace);
 }
 
 /**
  * hb_font_get_user_data: (skip)
  * @font: a font.
- * @key: 
+ * @key:
+ *
  *
- * 
  *
- * Return value: (transfer none): 
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
 void *
 hb_font_get_user_data (hb_font_t          *font,
 		       hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (font, key);
 }
 
 /**
  * hb_font_make_immutable:
  * @font: a font.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_make_immutable (hb_font_t *font)
 {
   if (hb_object_is_immutable (font))
     return;
@@ -1524,19 +1523,19 @@ hb_font_make_immutable (hb_font_t *font)
 
   hb_object_make_immutable (font);
 }
 
 /**
  * hb_font_is_immutable:
  * @font: a font.
  *
- * 
+ *
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_is_immutable (hb_font_t *font)
 {
   return hb_object_is_immutable (font);
 }
@@ -1566,19 +1565,19 @@ hb_font_set_parent (hb_font_t *font,
 
   hb_font_destroy (old);
 }
 
 /**
  * hb_font_get_parent:
  * @font: a font.
  *
- * 
+ *
  *
- * Return value: (transfer none): 
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_get_parent (hb_font_t *font)
 {
   return font->parent;
 }
@@ -1610,37 +1609,37 @@ hb_font_set_face (hb_font_t *font,
 
   hb_face_destroy (old);
 }
 
 /**
  * hb_font_get_face:
  * @font: a font.
  *
- * 
+ *
  *
- * Return value: (transfer none): 
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
 hb_face_t *
 hb_font_get_face (hb_font_t *font)
 {
   return font->face;
 }
 
 
 /**
  * hb_font_set_funcs:
  * @font: a font.
  * @klass: (closure font_data) (destroy destroy) (scope notified):
- * @font_data: 
- * @destroy: 
+ * @font_data:
+ * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_set_funcs (hb_font_t         *font,
 		   hb_font_funcs_t   *klass,
 		   void              *font_data,
 		   hb_destroy_func_t  destroy)
@@ -1664,19 +1663,19 @@ hb_font_set_funcs (hb_font_t         *fo
   font->user_data = font_data;
   font->destroy = destroy;
 }
 
 /**
  * hb_font_set_funcs_data:
  * @font: a font.
  * @font_data: (destroy destroy) (scope notified):
- * @destroy: 
+ * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_set_funcs_data (hb_font_t         *font,
 		        void              *font_data,
 		        hb_destroy_func_t  destroy)
 {
@@ -1694,20 +1693,20 @@ hb_font_set_funcs_data (hb_font_t       
   font->user_data = font_data;
   font->destroy = destroy;
 }
 
 
 /**
  * hb_font_set_scale:
  * @font: a font.
- * @x_scale: 
- * @y_scale: 
+ * @x_scale:
+ * @y_scale:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_set_scale (hb_font_t *font,
 		   int x_scale,
 		   int y_scale)
 {
@@ -1717,39 +1716,39 @@ hb_font_set_scale (hb_font_t *font,
   font->x_scale = x_scale;
   font->y_scale = y_scale;
   font->mults_changed ();
 }
 
 /**
  * hb_font_get_scale:
  * @font: a font.
- * @x_scale: (out): 
- * @y_scale: (out): 
+ * @x_scale: (out):
+ * @y_scale: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_get_scale (hb_font_t *font,
 		   int *x_scale,
 		   int *y_scale)
 {
   if (x_scale) *x_scale = font->x_scale;
   if (y_scale) *y_scale = font->y_scale;
 }
 
 /**
  * hb_font_set_ppem:
  * @font: a font.
- * @x_ppem: 
- * @y_ppem: 
+ * @x_ppem:
+ * @y_ppem:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_set_ppem (hb_font_t *font,
 		  unsigned int x_ppem,
 		  unsigned int y_ppem)
 {
@@ -1758,20 +1757,20 @@ hb_font_set_ppem (hb_font_t *font,
 
   font->x_ppem = x_ppem;
   font->y_ppem = y_ppem;
 }
 
 /**
  * hb_font_get_ppem:
  * @font: a font.
- * @x_ppem: (out): 
- * @y_ppem: (out): 
+ * @x_ppem: (out):
+ * @y_ppem: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_get_ppem (hb_font_t *font,
 		  unsigned int *x_ppem,
 		  unsigned int *y_ppem)
 {
@@ -1810,32 +1809,32 @@ hb_font_set_ptem (hb_font_t *font, float
  * Since: 0.9.2
  **/
 float
 hb_font_get_ptem (hb_font_t *font)
 {
   return font->ptem;
 }
 
+#ifndef HB_NO_VAR
 /*
  * Variations
  */
 
 static void
 _hb_font_adopt_var_coords_normalized (hb_font_t *font,
 				      int *coords, /* 2.14 normalized */
 				      unsigned int coords_length)
 {
   free (font->coords);
 
   font->coords = coords;
   font->num_coords = coords_length;
 }
 
-#ifndef HB_NO_VAR
 /**
  * hb_font_set_variations:
  *
  * Since: 1.4.2
  */
 void
 hb_font_set_variations (hb_font_t *font,
 			const hb_variation_t *variations,
@@ -1904,17 +1903,16 @@ hb_font_set_var_named_instance (hb_font_
   float *coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
   if (unlikely (coords_length && !coords))
     return;
 
   hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords);
   hb_font_set_var_coords_design (font, coords, coords_length);
   free (coords);
 }
-#endif
 
 /**
  * hb_font_set_var_coords_normalized:
  *
  * Since: 1.4.2
  */
 void
 hb_font_set_var_coords_normalized (hb_font_t *font,
@@ -1946,17 +1944,17 @@ const int *
 hb_font_get_var_coords_normalized (hb_font_t *font,
 				   unsigned int *length)
 {
   if (length)
     *length = font->num_coords;
 
   return font->coords;
 }
-
+#endif
 
 #ifndef HB_DISABLE_DEPRECATED
 /*
  * Deprecated get_glyph_func():
  */
 
 struct hb_trampoline_closure_t
 {
--- a/gfx/harfbuzz/src/hb-font.h
+++ b/gfx/harfbuzz/src/hb-font.h
@@ -219,17 +219,17 @@ hb_font_funcs_set_font_v_extents_func (h
 
 /**
  * hb_font_funcs_set_nominal_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.2.3
  **/
 HB_EXTERN void
 hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
 				      hb_font_get_nominal_glyph_func_t func,
 				      void *user_data, hb_destroy_func_t destroy);
 
@@ -251,193 +251,193 @@ hb_font_funcs_set_nominal_glyphs_func (h
 
 /**
  * hb_font_funcs_set_variation_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.2.3
  **/
 HB_EXTERN void
 hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_variation_glyph_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_h_advance_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_h_advance_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_v_advance_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_v_advance_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_h_advances_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_h_advances_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_v_advances_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_v_advances_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_h_origin_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
 				       hb_font_get_glyph_h_origin_func_t func,
 				       void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_v_origin_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
 				       hb_font_get_glyph_v_origin_func_t func,
 				       void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_h_kerning_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_h_kerning_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_extents_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
 				      hb_font_get_glyph_extents_func_t func,
 				      void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_contour_point_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
 					    hb_font_get_glyph_contour_point_func_t func,
 					    void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_name_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
 				   hb_font_get_glyph_name_func_t func,
 				   void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_from_name_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_from_name_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
--- a/gfx/harfbuzz/src/hb-ot-cff2-table.cc
+++ b/gfx/harfbuzz/src/hb-ot-cff2-table.cc
@@ -105,22 +105,20 @@ bool OT::cff2::accelerator_t::get_extent
 {
 #ifdef HB_NO_OT_FONT_CFF
   /* XXX Remove check when this code moves to .hh file. */
   return true;
 #endif
 
   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
 
-  unsigned int num_coords;
-  const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
   unsigned int fd = fdSelect->get_fd (glyph);
   cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t> interp;
   const byte_str_t str = (*charStrings)[glyph];
-  interp.env.init (str, *this, fd, coords, num_coords);
+  interp.env.init (str, *this, fd, font->coords, font->num_coords);
   cff2_extents_param_t  param;
   param.init ();
   if (unlikely (!interp.interpret (param))) return false;
 
   if (param.min_x >= param.max_x)
   {
     extents->width = 0;
     extents->x_bearing = 0;
--- a/gfx/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
@@ -988,35 +988,37 @@ struct cmap
   }
 
   const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
   {
     if (symbol) *symbol = false;
 
     const CmapSubtable *subtable;
 
+    /* Symbol subtable.
+     * Prefer symbol if available.
+     * https://github.com/harfbuzz/harfbuzz/issues/1918 */
+    if ((subtable = this->find_subtable (3, 0)))
+    {
+      if (symbol) *symbol = true;
+      return subtable;
+    }
+
     /* 32-bit subtables. */
     if ((subtable = this->find_subtable (3, 10))) return subtable;
     if ((subtable = this->find_subtable (0, 6))) return subtable;
     if ((subtable = this->find_subtable (0, 4))) return subtable;
 
     /* 16-bit subtables. */
     if ((subtable = this->find_subtable (3, 1))) return subtable;
     if ((subtable = this->find_subtable (0, 3))) return subtable;
     if ((subtable = this->find_subtable (0, 2))) return subtable;
     if ((subtable = this->find_subtable (0, 1))) return subtable;
     if ((subtable = this->find_subtable (0, 0))) return subtable;
 
-    /* Symbol subtable. */
-    if ((subtable = this->find_subtable (3, 0)))
-    {
-      if (symbol) *symbol = true;
-      return subtable;
-    }
-
     /* Meh. */
     return &Null (CmapSubtable);
   }
 
   struct accelerator_t
   {
     void init (hb_face_t *face)
     {
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -370,20 +370,24 @@ hb_ot_layout_get_ligature_carets (hb_fon
 				  hb_position_t  *caret_array /* OUT */)
 {
   unsigned int result_caret_count = 0;
   unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array);
   if (result)
   {
     if (caret_count) *caret_count = result_caret_count;
   }
+  else
+  {
 #ifndef HB_NO_AAT
-  else
     result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+#else
+    if (caret_count) *caret_count = 0;
 #endif
+  }
   return result;
 }
 #endif
 
 
 /*
  * GSUB/GPOS
  */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
@@ -126,23 +126,16 @@ indic_features[] =
    * lookups for init,pres,abvs,blws features.
    */
   {HB_TAG('i','n','i','t'),        F_MANUAL_JOINERS},
   {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
-  /*
-   * Positioning features.
-   * We don't care about the types.
-   */
-  {HB_TAG('d','i','s','t'), F_GLOBAL},
-  {HB_TAG('a','b','v','m'), F_GLOBAL},
-  {HB_TAG('b','l','w','m'), F_GLOBAL},
 };
 
 /*
  * Must be in the same order as the indic_features array.
  */
 enum {
   _INDIC_NUKT,
   _INDIC_AKHN,
@@ -158,20 +151,16 @@ enum {
 
   INDIC_INIT,
   _INDIC_PRES,
   _INDIC_ABVS,
   _INDIC_BLWS,
   _INDIC_PSTS,
   _INDIC_HALN,
 
-  _INDIC_DIST,
-  _INDIC_ABVM,
-  _INDIC_BLWM,
-
   INDIC_NUM_FEATURES,
   INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
 };
 
 static void
 setup_syllables_indic (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer);
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.cc
@@ -51,23 +51,16 @@ khmer_features[] =
   /*
    * Other features.
    * These features are applied all at once after clearing syllables.
    */
   {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
-  /*
-   * Positioning features.
-   * We don't care about the types.
-   */
-  {HB_TAG('d','i','s','t'), F_GLOBAL},
-  {HB_TAG('a','b','v','m'), F_GLOBAL},
-  {HB_TAG('b','l','w','m'), F_GLOBAL},
 };
 
 /*
  * Must be in the same order as the khmer_features array.
  */
 enum {
   KHMER_PREF,
   KHMER_BLWF,
@@ -75,20 +68,16 @@ enum {
   KHMER_PSTF,
   KHMER_CFAR,
 
   _KHMER_PRES,
   _KHMER_ABVS,
   _KHMER_BLWS,
   _KHMER_PSTS,
 
-  _KHMER_DIST,
-  _KHMER_ABVM,
-  _KHMER_BLWM,
-
   KHMER_NUM_FEATURES,
   KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */
 };
 
 static void
 setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer);
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
@@ -54,35 +54,16 @@ myanmar_other_features[] =
    * Other features.
    * These features are applied all at once, after clearing syllables.
    */
   HB_TAG('p','r','e','s'),
   HB_TAG('a','b','v','s'),
   HB_TAG('b','l','w','s'),
   HB_TAG('p','s','t','s'),
 };
-static const hb_tag_t
-myanmar_positioning_features[] =
-{
-  /*
-   * Positioning features.
-   * We don't care about the types.
-   */
-  HB_TAG('d','i','s','t'),
-  /* Pre-release version of Windows 8 Myanmar font had abvm,blwm
-   * features.  The released Windows 8 version of the font (as well
-   * as the released spec) used 'mark' instead.  The Windows 8
-   * shaper however didn't apply 'mark' but did apply 'mkmk'.
-   * Perhaps it applied abvm/blwm.  This was fixed in a Windows 8
-   * update, so now it applies mark/mkmk.  We are guessing that
-   * it still applies abvm/blwm too.
-   */
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-};
 
 static void
 setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
 			 hb_font_t *font,
 			 hb_buffer_t *buffer);
 static void
 reorder_myanmar (const hb_ot_shape_plan_t *plan,
 		 hb_font_t *font,
@@ -109,19 +90,16 @@ collect_features_myanmar (hb_ot_shape_pl
     map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ);
     map->add_gsub_pause (nullptr);
   }
 
   map->add_gsub_pause (_hb_clear_syllables);
 
   for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
     map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_positioning_features); i++)
-    map->enable_feature (myanmar_positioning_features[i]);
 }
 
 static void
 override_features_myanmar (hb_ot_shape_planner_t *plan)
 {
   plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
@@ -83,27 +83,16 @@ use_other_features[] =
    * clearing syllables.
    */
   HB_TAG('a','b','v','s'),
   HB_TAG('b','l','w','s'),
   HB_TAG('h','a','l','n'),
   HB_TAG('p','r','e','s'),
   HB_TAG('p','s','t','s'),
 };
-static const hb_tag_t
-use_positioning_features[] =
-{
-  /*
-   * Positioning features.
-   * We don't care about the types.
-   */
-  HB_TAG('d','i','s','t'),
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-};
 
 static void
 setup_syllables_use (const hb_ot_shape_plan_t *plan,
 		     hb_font_t *font,
 		     hb_buffer_t *buffer);
 static void
 record_rphf_use (const hb_ot_shape_plan_t *plan,
 		 hb_font_t *font,
@@ -149,20 +138,16 @@ collect_features_use (hb_ot_shape_planne
   /* "Topographical features" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
     map->add_feature (use_topographical_features[i]);
   map->add_gsub_pause (nullptr);
 
   /* "Standard typographic presentation" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (use_other_features); i++)
     map->enable_feature (use_other_features[i], F_MANUAL_ZWJ);
-
-  /* "Positional feature application" */
-  for (unsigned int i = 0; i < ARRAY_LENGTH (use_positioning_features); i++)
-    map->enable_feature (use_positioning_features[i]);
 }
 
 struct use_shape_plan_t
 {
   hb_mask_t rphf_mask;
 
   arabic_shape_plan_t *arabic_plan;
 };
--- a/gfx/harfbuzz/src/hb-ot-shape.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
@@ -280,30 +280,33 @@ hb_ot_shape_plan_t::position (hb_font_t 
     hb_aat_layout_track (this, font, buffer);
 #endif
 }
 
 
 static const hb_ot_map_feature_t
 common_features[] =
 {
+  {HB_TAG('a','b','v','m'), F_GLOBAL},
+  {HB_TAG('b','l','w','m'), F_GLOBAL},
   {HB_TAG('c','c','m','p'), F_GLOBAL},
   {HB_TAG('l','o','c','l'), F_GLOBAL},
   {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('m','k','m','k'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('r','l','i','g'), F_GLOBAL},
 };
 
 
 static const hb_ot_map_feature_t
 horizontal_features[] =
 {
   {HB_TAG('c','a','l','t'), F_GLOBAL},
   {HB_TAG('c','l','i','g'), F_GLOBAL},
   {HB_TAG('c','u','r','s'), F_GLOBAL},
+  {HB_TAG('d','i','s','t'), F_GLOBAL},
   {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK},
   {HB_TAG('l','i','g','a'), F_GLOBAL},
   {HB_TAG('r','c','l','t'), F_GLOBAL},
 };
 
 static void
 hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
 			      const hb_feature_t             *user_features,
--- a/gfx/harfbuzz/src/hb-ot-var-avar-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-var-avar-table.hh
@@ -44,32 +44,34 @@ struct AxisValueMap
 {
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   public:
-  F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
-				 * default normalization. */
-  F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
+  F2DOT14	coords[2];
+//   F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
+// 				 * default normalization. */
+//   F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
 
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct SegmentMaps : ArrayOf<AxisValueMap>
 {
-  int map (int value) const
+  int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
   {
+#define fromCoord coords[from_offset]
+#define toCoord coords[to_offset]
     /* The following special-cases are not part of OpenType, which requires
      * that at least -1, 0, and +1 must be mapped. But we include these as
      * part of a better error recovery scheme. */
-
     if (len < 2)
     {
       if (!len)
 	return value;
       else /* len == 1*/
 	return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
     }
 
@@ -86,18 +88,22 @@ struct SegmentMaps : ArrayOf<AxisValueMa
 
     if (unlikely (arrayZ[i-1].fromCoord == arrayZ[i].fromCoord))
       return arrayZ[i-1].toCoord;
 
     int denom = arrayZ[i].fromCoord - arrayZ[i-1].fromCoord;
     return arrayZ[i-1].toCoord +
 	   ((arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
 	    (value - arrayZ[i-1].fromCoord) + denom/2) / denom;
+#undef toCoord
+#undef fromCoord
   }
 
+  int unmap (int value) const { return map (value, 1, 0); }
+
   public:
   DEFINE_SIZE_ARRAY (2, *this);
 };
 
 struct avar
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
 
@@ -128,24 +134,36 @@ struct avar
     const SegmentMaps *map = &firstAxisSegmentMaps;
     for (unsigned int i = 0; i < count; i++)
     {
       coords[i] = map->map (coords[i]);
       map = &StructAfter<SegmentMaps> (*map);
     }
   }
 
+  void unmap_coords (int *coords, unsigned int coords_length) const
+  {
+    unsigned int count = hb_min (coords_length, axisCount);
+
+    const SegmentMaps *map = &firstAxisSegmentMaps;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      coords[i] = map->unmap (coords[i]);
+      map = &StructAfter<SegmentMaps> (*map);
+    }
+  }
+
   protected:
   FixedVersion<>version;	/* Version of the avar table
 				 * initially set to 0x00010000u */
   HBUINT16	reserved;	/* This field is permanently reserved. Set to 0. */
   HBUINT16	axisCount;	/* The number of variation axes in the font. This
 				 * must be the same number as axisCount in the
 				 * 'fvar' table. */
-  SegmentMaps   firstAxisSegmentMaps;
+  SegmentMaps	firstAxisSegmentMaps;
 
   public:
   DEFINE_SIZE_MIN (8);
 };
 
 } /* namespace OT */
 
 
--- a/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
@@ -235,16 +235,30 @@ struct fvar
       return 0;
     else if (v < axis.default_value)
       v = (v - axis.default_value) / (axis.default_value - axis.min_value);
     else
       v = (v - axis.default_value) / (axis.max_value - axis.default_value);
     return roundf (v * 16384.f);
   }
 
+  float unnormalize_axis_value (unsigned int axis_index, float v) const
+  {
+    hb_ot_var_axis_info_t axis;
+    get_axis_info (axis_index, &axis);
+
+    if (v == 0)
+      return axis.default_value;
+    else if (v < 0)
+      v = v * (axis.default_value - axis.min_value) / 16384.f + axis.default_value;
+    else
+      v = v * (axis.max_value - axis.default_value) / 16384.f + axis.default_value;
+    return v;
+  }
+
   unsigned int get_instance_count () const { return instanceCount; }
 
   hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int instance_index) const
   {
     const InstanceRecord *instance = get_instance (instance_index);
     if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
     return instance->subfamilyNameID;
   }
--- a/gfx/harfbuzz/src/hb-version.h
+++ b/gfx/harfbuzz/src/hb-version.h
@@ -33,19 +33,19 @@
 
 #include "hb-common.h"
 
 HB_BEGIN_DECLS
 
 
 #define HB_VERSION_MAJOR 2
 #define HB_VERSION_MINOR 6
-#define HB_VERSION_MICRO 0
+#define HB_VERSION_MICRO 1
 
-#define HB_VERSION_STRING "2.6.0"
+#define HB_VERSION_STRING "2.6.1"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
 
 
 HB_EXTERN void
 hb_version (unsigned int *major,
--- a/gfx/harfbuzz/update.sh
+++ b/gfx/harfbuzz/update.sh
@@ -1,16 +1,16 @@
 #!/bin/sh
 
 # Script to update the mozilla in-tree copy of the HarfBuzz library.
 # Run this within the /gfx/harfbuzz directory of the source tree.
 
 MY_TEMP_DIR=`mktemp -d -t harfbuzz_update.XXXXXX` || exit 1
 
-VERSION=2.6.0
+VERSION=2.6.1
 
 git clone https://github.com/harfbuzz/harfbuzz ${MY_TEMP_DIR}/harfbuzz
 git -C ${MY_TEMP_DIR}/harfbuzz checkout ${VERSION}
 
 COMMIT=$(git -C ${MY_TEMP_DIR}/harfbuzz rev-parse HEAD)
 perl -p -i -e "s/(\d+\.)(\d+\.)(\d+)/${VERSION}/" README-mozilla;
 perl -p -i -e "s/\[commit [0-9a-f]{40}\]/[commit ${COMMIT}]/" README-mozilla;