[API] Add hb_buffer_[sg]et_not_found_glyph() and --not-found-glyph

Instead of using gid=0 when a character is not found in the font,
client can now set a custom value.  This is useful for shaper-driven
font fallback and to differentiate that from .notdef glyph.

Fixes https://github.com/harfbuzz/harfbuzz/issues/1360
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index bb8040f..f2c7593 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -85,6 +85,8 @@
 hb_buffer_has_positions
 hb_buffer_get_invisible_glyph
 hb_buffer_set_invisible_glyph
+hb_buffer_get_not_found_glyph
+hb_buffer_set_not_found_glyph
 hb_buffer_set_replacement_codepoint
 hb_buffer_get_replacement_codepoint
 hb_buffer_normalize_glyphs
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index c6591ca..caa5629 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -224,6 +224,7 @@
   flags = HB_BUFFER_FLAG_DEFAULT;
   replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
   invisible = 0;
+  not_found = 0;
 
   clear ();
 }
@@ -608,6 +609,7 @@
   HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
   HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
   0, /* invisible */
+  0, /* not_found */
   HB_BUFFER_SCRATCH_FLAG_DEFAULT,
   HB_BUFFER_MAX_LEN_DEFAULT,
   HB_BUFFER_MAX_OPS_DEFAULT,
@@ -1158,6 +1160,46 @@
   return buffer->invisible;
 }
 
+/**
+ * hb_buffer_set_not_found_glyph:
+ * @buffer: An #hb_buffer_t
+ * @not_found: the not-found #hb_codepoint_t
+ *
+ * Sets the #hb_codepoint_t that replaces characters not found in
+ * the font during shaping.
+ *
+ * The not-found glyph defaults to zero, sometimes knows as the
+ * ".notdef" glyph.  This API allows for differentiating the two.
+ *
+ * Since: REPLACEME
+ **/
+void
+hb_buffer_set_not_found_glyph (hb_buffer_t    *buffer,
+			       hb_codepoint_t  not_found)
+{
+  if (unlikely (hb_object_is_immutable (buffer)))
+    return;
+
+  buffer->not_found = not_found;
+}
+
+/**
+ * hb_buffer_get_not_found_glyph:
+ * @buffer: An #hb_buffer_t
+ *
+ * See hb_buffer_set_not_found_glyph().
+ *
+ * Return value:
+ * The @buffer not-found #hb_codepoint_t
+ *
+ * Since: REPLACEME
+ **/
+hb_codepoint_t
+hb_buffer_get_not_found_glyph (hb_buffer_t    *buffer)
+{
+  return buffer->not_found;
+}
+
 
 /**
  * hb_buffer_reset:
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 865ccb2..a183cb9 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -383,6 +383,13 @@
 HB_EXTERN hb_codepoint_t
 hb_buffer_get_invisible_glyph (hb_buffer_t    *buffer);
 
+HB_EXTERN void
+hb_buffer_set_not_found_glyph (hb_buffer_t    *buffer,
+			       hb_codepoint_t  not_found);
+
+HB_EXTERN hb_codepoint_t
+hb_buffer_get_not_found_glyph (hb_buffer_t    *buffer);
+
 
 HB_EXTERN void
 hb_buffer_reset (hb_buffer_t *buffer);
diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh
index 8635ebd..bde2893 100644
--- a/src/hb-buffer.hh
+++ b/src/hb-buffer.hh
@@ -93,6 +93,7 @@
   hb_buffer_cluster_level_t cluster_level;
   hb_codepoint_t replacement; /* U+FFFD or something else. */
   hb_codepoint_t invisible; /* 0 or something else. */
+  hb_codepoint_t not_found; /* 0 or something else. */
   hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
   unsigned int max_len; /* Maximum allowed len. */
   int max_ops; /* Maximum allowed operations. */
diff --git a/src/hb-font.hh b/src/hb-font.hh
index 8fc7f44..dd5cd13 100644
--- a/src/hb-font.hh
+++ b/src/hb-font.hh
@@ -217,9 +217,10 @@
   }
 
   hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
-			       hb_codepoint_t *glyph)
+			       hb_codepoint_t *glyph,
+			       hb_codepoint_t not_found = 0)
   {
-    *glyph = 0;
+    *glyph = not_found;
     return klass->get.f.nominal_glyph (this, user_data,
 				       unicode, glyph,
 				       klass->user_data.nominal_glyph);
@@ -238,9 +239,10 @@
   }
 
   hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-				 hb_codepoint_t *glyph)
+				 hb_codepoint_t *glyph,
+				 hb_codepoint_t not_found = 0)
   {
-    *glyph = 0;
+    *glyph = not_found;
     return klass->get.f.variation_glyph (this, user_data,
 					 unicode, variation_selector, glyph,
 					 klass->user_data.variation_glyph);
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 778b5b8..839cc91 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -171,7 +171,7 @@
   hb_codepoint_t u = buffer->cur().codepoint;
   hb_codepoint_t glyph = 0;
 
-  if (shortest && c->font->get_nominal_glyph (u, &glyph))
+  if (shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found))
   {
     next_char (buffer, glyph);
     return;
@@ -183,7 +183,7 @@
     return;
   }
 
-  if (!shortest && c->font->get_nominal_glyph (u, &glyph))
+  if (!shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found))
   {
     next_char (buffer, glyph);
     return;
@@ -312,6 +312,7 @@
     buffer,
     font,
     buffer->unicode,
+    buffer->not_found,
     plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode,
     plan->shaper->compose   ? plan->shaper->compose   : compose_unicode
   };
diff --git a/src/hb-ot-shape-normalize.hh b/src/hb-ot-shape-normalize.hh
index 04f1a80..12c78a2 100644
--- a/src/hb-ot-shape-normalize.hh
+++ b/src/hb-ot-shape-normalize.hh
@@ -56,6 +56,7 @@
   hb_buffer_t *buffer;
   hb_font_t *font;
   hb_unicode_funcs_t *unicode;
+  const hb_codepoint_t not_found;
   bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
 		     hb_codepoint_t  ab,
 		     hb_codepoint_t *a,
diff --git a/util/shape-options.hh b/util/shape-options.hh
index 6484085..8d33184 100644
--- a/util/shape-options.hh
+++ b/util/shape-options.hh
@@ -55,6 +55,7 @@
 				  (remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) |
 				  0));
     hb_buffer_set_invisible_glyph (buffer, invisible_glyph);
+    hb_buffer_set_not_found_glyph (buffer, not_found_glyph);
     hb_buffer_set_cluster_level (buffer, cluster_level);
     hb_buffer_guess_segment_properties (buffer);
   }
@@ -305,6 +306,7 @@
   char **shapers = nullptr;
   hb_bool_t utf8_clusters = false;
   hb_codepoint_t invisible_glyph = 0;
+  hb_codepoint_t not_found_glyph = 0;
   hb_buffer_cluster_level_t cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
   hb_bool_t normalize_glyphs = false;
   hb_bool_t verify = false;
@@ -427,6 +429,7 @@
     {"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE,	&this->preserve_default_ignorables,	"Preserve Default-Ignorable characters",	nullptr},
     {"remove-default-ignorables",0, 0, G_OPTION_ARG_NONE,	&this->remove_default_ignorables,	"Remove Default-Ignorable characters",	nullptr},
     {"invisible-glyph",	0, 0, G_OPTION_ARG_INT,		&this->invisible_glyph,		"Glyph value to replace Default-Ignorables with",	nullptr},
+    {"not-found-glyph",	0, 0, G_OPTION_ARG_INT,		&this->not_found_glyph,		"Glyph value to replace not-found characters with",	nullptr},
     {"utf8-clusters",	0, 0, G_OPTION_ARG_NONE,	&this->utf8_clusters,		"Use UTF8 byte indices, not char indices",	nullptr},
     {"cluster-level",	0, 0, G_OPTION_ARG_INT,		&this->cluster_level,		"Cluster merging level (default: 0)",	"0/1/2"},
     {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE,	&this->normalize_glyphs,	"Rearrange glyph clusters in nominal order",	nullptr},