[HarfBuzz] harfbuzz: Branch 'master' - 6 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Mon Jan 23 03:52:35 UTC 2017


 docs/harfbuzz-sections.txt  |   10 ++-
 src/Makefile.sources        |    1 
 src/hb-font.cc              |   25 ++-----
 src/hb-font.h               |    2 
 src/hb-ft.cc                |    2 
 src/hb-ot-math.cc           |    2 
 src/hb-ot-var-avar-table.hh |  143 ++++++++++++++++++++++++++++++++++++++++++++
 src/hb-ot-var.cc            |   64 ++++++++++++++++---
 src/hb-ot-var.h             |   22 +++++-
 util/helper-cairo.cc        |   14 ++--
 util/options.cc             |   53 ++++------------
 11 files changed, 257 insertions(+), 81 deletions(-)

New commits:
commit 7a860f656e4aec45c45e0f5fb28c49a91dc5eef2
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Jan 22 19:52:09 2017 -0800

    [var] Add macros for standard axes

diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index fcf4e52..3011ee9 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -442,6 +442,11 @@ Xhb_ot_layout_lookup_substitute
 <FILE>hb-ot-var</FILE>
 HB_OT_TAG_avar
 HB_OT_TAG_fvar
+HB_OT_TAG_VAR_AXIS_ITALIC
+HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
+HB_OT_TAG_VAR_AXIS_SLANT
+HB_OT_TAG_VAR_AXIS_WEIGHT
+HB_OT_TAG_VAR_AXIS_WIDTH
 HB_OT_VAR_NO_AXIS_INDEX
 hb_ot_var_axis_t
 hb_ot_var_has_data
@@ -584,6 +589,8 @@ hb_unicode_script_func_t
 <FILE>hb-uniscribe</FILE>
 hb_uniscribe_font_get_hfont
 hb_uniscribe_font_get_logfontw
+<SUBSECTION Private>
+hb_directwrite_shape_experimental_width
 </SECTION>
 
 <SECTION>
diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h
index bce7c7a..ea69aa5 100644
--- a/src/hb-ot-var.h
+++ b/src/hb-ot-var.h
@@ -39,6 +39,12 @@ HB_BEGIN_DECLS
 #define HB_OT_TAG_fvar HB_TAG('f','v','a','r')
 #define HB_OT_TAG_avar HB_TAG('a','v','a','r')
 
+#define HB_OT_TAG_VAR_AXIS_ITALIC	HB_TAG('i','t','a','l')
+#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE	HB_TAG('o','p','s','z')
+#define HB_OT_TAG_VAR_AXIS_SLANT	HB_TAG('s','l','n','t')
+#define HB_OT_TAG_VAR_AXIS_WIDTH	HB_TAG('w','d','t','h')
+#define HB_OT_TAG_VAR_AXIS_WEIGHT	HB_TAG('w','g','h','t')
+
 
 /*
  * fvar / avar
commit a484e237b11650d00092329855d33dd2f67980e4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Jan 22 19:41:33 2017 -0800

    [var] Implement 'avar' table mapping
    
    Untested!

diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc
index eb08bad..2d7e679 100644
--- a/src/hb-ot-math.cc
+++ b/src/hb-ot-math.cc
@@ -34,9 +34,7 @@ static inline const OT::MATH&
 _get_math (hb_face_t *face)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH);
-
   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-
   return *(layout->math.get ());
 }
 
diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh
index a041934..743d587 100644
--- a/src/hb-ot-var-avar-table.hh
+++ b/src/hb-ot-var-avar-table.hh
@@ -50,7 +50,39 @@ struct AxisValueMap
   DEFINE_SIZE_STATIC (4);
 };
 
-typedef ArrayOf<AxisValueMap> SegmentMaps;
+struct SegmentMaps : ArrayOf<AxisValueMap>
+{
+  inline int map (int value) const
+  {
+    /* The following special-cases are not part of OpenType, which requires
+     * that at least -1, 0, and +1 must be mapped. But we include these as
+     * part of a better error recovery scheme. */
+
+    if (!len)
+      return value;
+
+    if (value <= array[0].fromCoord)
+      return value - array[0].fromCoord + array[0].toCoord;
+
+    unsigned int i;
+    unsigned int count = len;
+    for (i = 1; i < count && value > array[i].fromCoord; i++)
+      ;
+
+    if (value >= array[i].fromCoord)
+      return value - array[i].fromCoord + array[i].toCoord;
+
+    if (unlikely (array[i-1].fromCoord == array[i].fromCoord))
+      return array[i-1].toCoord;
+
+    int denom = array[i].fromCoord - array[i-1].fromCoord;
+    return array[i-1].toCoord +
+	   (array[i].toCoord - array[i-1].toCoord) *
+	   (value - array[i-1].fromCoord + denom/2) / denom;
+  }
+
+  DEFINE_SIZE_ARRAY (2, array);
+};
 
 /*
  * avar — Axis Variations Table
@@ -80,6 +112,18 @@ struct avar
     return_trace (true);
   }
 
+  inline void map_coords (int *coords, unsigned int coords_length) const
+  {
+    unsigned int count = MIN<unsigned int> (coords_length, axisCount);
+
+    const SegmentMaps *map = &axisSegmentMapsZ;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      coords[i] = map->map (coords[i]);
+      map = &StructAfter<SegmentMaps> (*map);
+    }
+  }
+
   protected:
   FixedVersion<>version;	/* Version of the avar table
 				 * initially set to 0x00010000u */
diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc
index 76016e6..d4d16df 100644
--- a/src/hb-ot-var.cc
+++ b/src/hb-ot-var.cc
@@ -33,19 +33,24 @@
 
 HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
 
+/*
+ * fvar/avar
+ */
+
 static inline const OT::fvar&
 _get_fvar (hb_face_t *face)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar);
-
   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-
   return *(layout->fvar.get ());
 }
-
-/*
- * fvar/avar
- */
+static inline const OT::avar&
+_get_avar (hb_face_t *face)
+{
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::avar);
+  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+  return *(layout->avar.get ());
+}
 
 /**
  * hb_ot_var_has_data:
@@ -131,7 +136,8 @@ hb_ot_var_normalize_variations (hb_face_t            *face,
       coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
   }
 
-  /* TODO avar */
+  const OT::avar &avar = _get_avar (face);
+  avar.map_coords (coords, coords_length);
 }
 
 /**
@@ -149,5 +155,6 @@ hb_ot_var_normalize_coords (hb_face_t    *face,
   for (unsigned int i = 0; i < coords_length; i++)
     normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
 
-  /* TODO avar */
+  const OT::avar &avar = _get_avar (face);
+  avar.map_coords (normalized_coords, coords_length);
 }
commit a42909057207cbed1ef95716170434c05beb0002
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Jan 22 19:01:07 2017 -0800

    [var] Flesh out --variations documentation

diff --git a/util/options.cc b/util/options.cc
index 8c79c4a..0f2e207 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -311,7 +311,7 @@ view_options_t::add_options (option_parser_t *parser)
   parser->add_group (entries,
 		     "view",
 		     "View options:",
-		     "Options controlling output rendering",
+		     "Options for output rendering",
 		     this);
 }
 
@@ -340,7 +340,7 @@ shape_options_t::add_options (option_parser_t *parser)
   parser->add_group (entries,
 		     "shape",
 		     "Shape options:",
-		     "Options controlling the shaping process",
+		     "Options for the shaping process",
 		     this);
 
   const gchar *features_help = "Comma-separated list of font features\n"
@@ -387,7 +387,7 @@ shape_options_t::add_options (option_parser_t *parser)
   parser->add_group (entries2,
 		     "features",
 		     "Features options:",
-		     "Options controlling font features used",
+		     "Options for font features used",
 		     this);
 }
 
@@ -454,45 +454,20 @@ font_options_t::add_options (option_parser_t *parser)
   parser->add_group (entries,
 		     "font",
 		     "Font options:",
-		     "Options controlling the font",
+		     "Options for the font",
 		     this);
 
   const gchar *variations_help = "Comma-separated list of font variations\n"
     "\n"
-    "    XXXXXXXXXXXXXXX\n"
-    "    Features can be enabled or disabled, either globally or limited to\n"
-    "    specific character ranges.  The format for specifying feature settings\n"
-    "    follows.  All valid CSS font-feature-settings values other than 'normal'\n"
+    "    Variations are set globally. The format for specifying variation settings\n"
+    "    follows.  All valid CSS font-variation-settings values other than 'normal'\n"
     "    and 'inherited' are also accepted, though, not documented below.\n"
     "\n"
-    "    The range indices refer to the positions between Unicode characters,\n"
-    "    unless the --utf8-clusters is provided, in which case range indices\n"
-    "    refer to UTF-8 byte indices. The position before the first character\n"
-    "    is always 0.\n"
-    "\n"
-    "    The format is Python-esque.  Here is how it all works:\n"
-    "\n"
-    "      Syntax:       Value:    Start:    End:\n"
-    "\n"
-    "    Setting value:\n"
-    "      \"kern\"        1         0         ∞         # Turn feature on\n"
-    "      \"+kern\"       1         0         ∞         # Turn feature on\n"
-    "      \"-kern\"       0         0         ∞         # Turn feature off\n"
-    "      \"kern=0\"      0         0         ∞         # Turn feature off\n"
-    "      \"kern=1\"      1         0         ∞         # Turn feature on\n"
-    "      \"aalt=2\"      2         0         ∞         # Choose 2nd alternate\n"
-    "\n"
-    "    Setting index:\n"
-    "      \"kern[]\"      1         0         ∞         # Turn feature on\n"
-    "      \"kern[:]\"     1         0         ∞         # Turn feature on\n"
-    "      \"kern[5:]\"    1         5         ∞         # Turn feature on, partial\n"
-    "      \"kern[:5]\"    1         0         5         # Turn feature on, partial\n"
-    "      \"kern[3:5]\"   1         3         5         # Turn feature on, range\n"
-    "      \"kern[3]\"     1         3         3+1       # Turn feature on, single char\n"
+    "    The format is a tag, optionally followed by an equals sign, followed by a\n"
+    "    number. For example:\n"
     "\n"
-    "    Mixing it all:\n"
-    "\n"
-    "      \"aalt[3:5]=2\" 2         3         5         # Turn 2nd alternate on for range";
+    "      \"wght=500\"\n"
+    "      \"slnt=-7.5\"\n";
 
   GOptionEntry entries2[] =
   {
@@ -502,7 +477,7 @@ font_options_t::add_options (option_parser_t *parser)
   parser->add_group (entries2,
 		     "variations",
 		     "Varitions options:",
-		     "Options controlling font variations used",
+		     "Options for font variations used",
 		     this);
 }
 
@@ -520,7 +495,7 @@ text_options_t::add_options (option_parser_t *parser)
   parser->add_group (entries,
 		     "text",
 		     "Text options:",
-		     "Options controlling the input text",
+		     "Options for the input text",
 		     this);
 }
 
@@ -548,7 +523,7 @@ output_options_t::add_options (option_parser_t *parser)
   parser->add_group (entries,
 		     "output",
 		     "Output destination & format options:",
-		     "Options controlling the destination and form of the output",
+		     "Options for the destination & form of the output",
 		     this);
 }
 
@@ -810,7 +785,7 @@ format_options_t::add_options (option_parser_t *parser)
          "    text: [<glyph name or index>=<glyph cluster index within input>@<horizontal displacement>,<vertical displacement>+<horizontal advance>,<vertical advance>|...]\n"
          "    json: [{\"g\": <glyph name or index>, \"ax\": <horizontal advance>, \"ay\": <vertical advance>, \"dx\": <horizontal displacement>, \"dy\": <vertical displacement>, \"cl\": <glyph cluster index within input>}, ...]\n"
          "\nOutput syntax options:",
-		     "Options controlling the syntax of the output",
+		     "Options for the syntax of the output",
 		     this);
 }
 
commit 5ec96d30cad1592b5e468bd8ad1832dbaf0ad32b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Jan 22 18:52:00 2017 -0800

    [var] Adjust API in prep for 'avar' implementation
    
    The 'avar' table does not allow random access to axis maps,
    so change API to avoid quadratic-time implementation.
    
    Removed -hb_ot_var_normalize_axis_value(), added
    +hb_ot_var_normalize_variations() and
    +hb_ot_var_normalize_coords() instead.

diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index b4ae15d..fcf4e52 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -448,7 +448,8 @@ hb_ot_var_has_data
 hb_ot_var_find_axis
 hb_ot_var_get_axis_count
 hb_ot_var_get_axes
-hb_ot_var_normalize_axis_value
+hb_ot_var_normalize_variations
+hb_ot_var_normalize_coords
 </SECTION>
 
 <SECTION>
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 279bc46..c74147c 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -109,6 +109,7 @@ HB_OT_sources = \
 	hb-ot-shape-fallback.cc \
 	hb-ot-shape-private.hh \
 	hb-ot-var.cc \
+	hb-ot-var-avar-table.hh \
 	hb-ot-var-fvar-table.hh \
 	$(NULL)
 
diff --git a/src/hb-font.cc b/src/hb-font.cc
index a3f250d..ea45501 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -1570,22 +1570,15 @@ hb_font_set_variations (hb_font_t *font,
     return;
   }
 
-  hb_face_t *face = font->face;
-
-  unsigned int coords_length = hb_ot_var_get_axis_count (face);
+  unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
 
   int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL;
   if (unlikely (coords_length && !normalized))
     return;
 
-  /* normalized is filled with zero already. */
-  for (unsigned int i = 0; i < variations_length; i++)
-  {
-    unsigned int axis_index;
-    if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, NULL))
-      normalized[axis_index] = hb_ot_var_normalize_axis_value (face, axis_index, variations[i].value);
-  }
-
+  hb_ot_var_normalize_variations (font->face,
+				  variations, variations_length,
+				  normalized, coords_length);
   _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
 }
 
@@ -1606,10 +1599,7 @@ hb_font_set_var_coords_design (hb_font_t *font,
   if (unlikely (coords_length && !normalized))
     return;
 
-  hb_face_t *face = font->face;
-  for (unsigned int i = 0; i < coords_length; i++)
-    normalized[i] = hb_ot_var_normalize_axis_value (face, i, coords[i]);
-
+  hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
   _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
 }
 
diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc
index 5080424..76016e6 100644
--- a/src/hb-ot-var.cc
+++ b/src/hb-ot-var.cc
@@ -27,6 +27,7 @@
 #include "hb-open-type-private.hh"
 
 #include "hb-ot-layout-private.hh"
+#include "hb-ot-var-avar-table.hh"
 #include "hb-ot-var-fvar-table.hh"
 #include "hb-ot-var.h"
 
@@ -105,16 +106,48 @@ hb_ot_var_find_axis (hb_face_t        *face,
   return fvar.find_axis (axis_tag, axis_index, axis_info);
 }
 
+
+/**
+ * hb_ot_var_normalize_variations:
+ *
+ * Since: 1.4.2
+ **/
+void
+hb_ot_var_normalize_variations (hb_face_t            *face,
+				const hb_variation_t *variations, /* IN */
+				unsigned int          variations_length,
+				int                  *coords, /* OUT */
+				unsigned int          coords_length)
+{
+  for (unsigned int i = 0; i < coords_length; i++)
+    coords[i] = 0;
+
+  const OT::fvar &fvar = _get_fvar (face);
+  for (unsigned int i = 0; i < variations_length; i++)
+  {
+    unsigned int axis_index;
+    if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, NULL) &&
+	axis_index < coords_length)
+      coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
+  }
+
+  /* TODO avar */
+}
+
 /**
- * hb_ot_var_normalize_axis_value:
+ * hb_ot_var_normalize_coords:
  *
  * Since: 1.4.2
  **/
-int
-hb_ot_var_normalize_axis_value (hb_face_t    *face,
-				unsigned int  axis_index,
-				float         v)
+void
+hb_ot_var_normalize_coords (hb_face_t    *face,
+			    unsigned int coords_length,
+			    const float *design_coords, /* IN */
+			    int *normalized_coords /* OUT */)
 {
   const OT::fvar &fvar = _get_fvar (face);
-  return fvar.normalize_axis_value (axis_index, v);
+  for (unsigned int i = 0; i < coords_length; i++)
+    normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
+
+  /* TODO avar */
 }
diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h
index 652a78d..bce7c7a 100644
--- a/src/hb-ot-var.h
+++ b/src/hb-ot-var.h
@@ -83,10 +83,18 @@ hb_ot_var_find_axis (hb_face_t        *face,
 		     hb_ot_var_axis_t *axis_info);
 
 
-HB_EXTERN int
-hb_ot_var_normalize_axis_value (hb_face_t    *face,
-				unsigned int  axis_index,
-				float         v);
+HB_EXTERN void
+hb_ot_var_normalize_variations (hb_face_t            *face,
+				const hb_variation_t *variations, /* IN */
+				unsigned int          variations_length,
+				int                  *coords, /* OUT */
+				unsigned int          coords_length);
+
+HB_EXTERN void
+hb_ot_var_normalize_coords (hb_face_t    *face,
+			    unsigned int coords_length,
+			    const float *design_coords, /* IN */
+			    int *normalized_coords /* OUT */);
 
 
 HB_END_DECLS
commit 8a577aaa0dd760409bcad1ae3d4f5fb561a62a4b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Jan 22 18:22:40 2017 -0800

    [var] Stub implementation of avar table

diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh
new file mode 100644
index 0000000..a041934
--- /dev/null
+++ b/src/hb-ot-var-avar-table.hh
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_VAR_AVAR_TABLE_HH
+#define HB_OT_VAR_AVAR_TABLE_HH
+
+#include "hb-open-type-private.hh"
+#include "hb-ot-var.h"
+
+namespace OT {
+
+
+struct AxisValueMap
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
+				 * default normalization. */
+  F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+typedef ArrayOf<AxisValueMap> SegmentMaps;
+
+/*
+ * avar — Axis Variations Table
+ */
+
+struct avar
+{
+  static const hb_tag_t tableTag	= HB_OT_TAG_avar;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(version.sanitize (c) &&
+		    version.major == 1 &&
+		    c->check_struct (this))))
+      return_trace (false);
+
+    const SegmentMaps *map = &axisSegmentMapsZ;
+    unsigned int count = axisCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (unlikely (!map->sanitize (c)))
+        return_trace (false);
+      map = &StructAfter<SegmentMaps> (*map);
+    }
+
+    return_trace (true);
+  }
+
+  protected:
+  FixedVersion<>version;	/* Version of the avar table
+				 * initially set to 0x00010000u */
+  USHORT	reserved;	/* This field is permanently reserved. Set to 0. */
+  USHORT	axisCount;	/* The number of variation axes in the font. This
+				 * must be the same number as axisCount in the
+				 * 'fvar' table. */
+  SegmentMaps	axisSegmentMapsZ;
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_VAR_AVAR_TABLE_HH */
commit 7647a05a0b37c53465560952b412db4e590f2716
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Jan 22 17:47:49 2017 -0800

    Minor

diff --git a/src/hb-font.cc b/src/hb-font.cc
index 3140ee4..a3f250d 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -1639,9 +1639,12 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
 /**
  * hb_font_set_var_coords_normalized:
  *
+ * Return value is valid as long as variation coordinates of the font
+ * are not modified.
+ *
  * Since: 1.4.2
  */
-int *
+const int *
 hb_font_get_var_coords_normalized (hb_font_t *font,
 				   unsigned int *length)
 {
diff --git a/src/hb-font.h b/src/hb-font.h
index fce4206..e2e5979 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -618,7 +618,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
 				   const int *coords, /* 2.14 normalized */
 				   unsigned int coords_length);
 
-HB_EXTERN int *
+HB_EXTERN const int *
 hb_font_get_var_coords_normalized (hb_font_t *font,
 				   unsigned int *length);
 
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 496fff2..48d6a0e 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -742,7 +742,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
   }
 
   unsigned int num_coords;
-  int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
+  const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
   if (num_coords)
   {
     FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
diff --git a/util/helper-cairo.cc b/util/helper-cairo.cc
index df5173b..2e2952b 100644
--- a/util/helper-cairo.cc
+++ b/util/helper-cairo.cc
@@ -104,13 +104,17 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
   else
   {
     unsigned int num_coords;
-    int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
+    const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
     if (num_coords)
     {
-      FT_Fixed ft_coords[num_coords];
-      for (unsigned int i = 0; i < num_coords; i++)
-        ft_coords[i] = coords[i] << 2;
-      FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
+      FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
+      if (ft_coords)
+      {
+	for (unsigned int i = 0; i < num_coords; i++)
+	  ft_coords[i] = coords[i] << 2;
+	FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
+	free (ft_coords);
+      }
     }
 
     cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);


More information about the HarfBuzz mailing list