From 97a9e4e41e9712fa52802d1043b7cecdde2ff2a2 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad@behdad.org>
Date: Wed, 11 Aug 2021 19:28:16 -0600
Subject: [PATCH] [util] Separate shape_text_options_t from text_options_t

---
 util/hb-ot-shape-closure.cc | 15 +++++---
 util/hb-shape.cc            |  2 +-
 util/hb-subset.cc           | 14 ++++---
 util/hb-view.cc             |  2 +-
 util/main-font-text.hh      |  6 +--
 util/shape-consumer.hh      | 16 +++++---
 util/text-options.hh        | 73 +++++++++++++++++++++++++++++++++----
 7 files changed, 98 insertions(+), 30 deletions(-)

diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc
index 874ddd728..1cfdf34cc 100644
--- a/util/hb-ot-shape-closure.cc
+++ b/util/hb-ot-shape-closure.cc
@@ -61,16 +61,19 @@ struct shape_closure_consumer_t
     failed = false;
     buffer = hb_buffer_create ();
   }
-  void consume_line (const char   *text,
-		     unsigned int  text_len,
-		     const char   *text_before,
-		     const char   *text_after)
+  template <typename text_options_t>
+  bool consume_line (text_options_t &text_opts)
   {
+    unsigned int text_len;
+    const char *text;
+    if (!(text = text_opts.get_line (&text_len)))
+      return false;
+
     hb_set_clear (glyphs);
     shaper.shape_closure (text, text_len, font, buffer, glyphs);
 
     if (hb_set_is_empty (glyphs))
-      return;
+      return true;
 
     /* Print it out! */
     bool first = true;
@@ -88,6 +91,8 @@ struct shape_closure_consumer_t
       } else
 	printf ("%u", i);
     }
+
+    return true;
   }
   void finish (const font_options_t *font_opts)
   {
diff --git a/util/hb-shape.cc b/util/hb-shape.cc
index 6b274ecc7..35cad0324 100644
--- a/util/hb-shape.cc
+++ b/util/hb-shape.cc
@@ -161,6 +161,6 @@ struct output_buffer_t : output_options_t
 int
 main (int argc, char **argv)
 {
-  using main_t = main_font_text_t<shape_consumer_t<output_buffer_t>, font_options_t, text_options_t>;
+  using main_t = main_font_text_t<shape_consumer_t<output_buffer_t>, font_options_t, shape_text_options_t>;
   return batch_main<main_t> (argc, argv);
 }
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 6664ed48c..1bbeb7f6f 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -52,17 +52,19 @@ struct subset_consumer_t : subset_options_t, output_options_t
     face = hb_face_reference (face_opts->face);
   }
 
-  void consume_line (const char   *text,
-		     unsigned int  text_len,
-		     const char   *text_before,
-		     const char   *text_after)
+  bool consume_line (text_options_t &text_opts)
   {
+    unsigned int text_len;
+    const char *text;
+    if (!(text = text_opts.get_line (&text_len)))
+      return false;
+
     // TODO does this only get called with at least 1 codepoint?
     hb_set_t *codepoints = hb_subset_input_unicode_set (input);
     if (0 == strcmp (text, "*"))
     {
       hb_face_collect_unicodes (face, codepoints);
-      return;
+      return true;
     }
 
     gchar *c = (gchar *)text;
@@ -71,6 +73,8 @@ struct subset_consumer_t : subset_options_t, output_options_t
       hb_codepoint_t hb_cp = cp;
       hb_set_add (codepoints, hb_cp);
     } while ((c = g_utf8_find_next_char(c, text + text_len)));
+
+    return true;
   }
 
   hb_bool_t
diff --git a/util/hb-view.cc b/util/hb-view.cc
index 7ecaa3709..2664c7c81 100644
--- a/util/hb-view.cc
+++ b/util/hb-view.cc
@@ -37,5 +37,5 @@ const unsigned SUBPIXEL_BITS = 6;
 int
 main (int argc, char **argv)
 {
-  return main_font_text_t<shape_consumer_t<view_cairo_t>, font_options_t, text_options_t> () (argc, argv);
+  return main_font_text_t<shape_consumer_t<view_cairo_t>, font_options_t, shape_text_options_t> () (argc, argv);
 }
diff --git a/util/main-font-text.hh b/util/main-font-text.hh
index a2a439170..dabbd3285 100644
--- a/util/main-font-text.hh
+++ b/util/main-font-text.hh
@@ -41,10 +41,8 @@ struct main_font_text_t : option_parser_t, font_options_t, text_options_t, consu
 
     this->init (this);
 
-    unsigned int line_len;
-    const char *line;
-    while ((line = this->get_line (&line_len)))
-      this->consume_line (line, line_len, this->text_before, this->text_after);
+    while (this->consume_line (*this))
+      ;
 
     this->finish (this);
 
diff --git a/util/shape-consumer.hh b/util/shape-consumer.hh
index cbbac2202..333e5e876 100644
--- a/util/shape-consumer.hh
+++ b/util/shape-consumer.hh
@@ -29,6 +29,7 @@
 
 #include "font-options.hh"
 #include "shape-options.hh"
+#include "text-options.hh"
 
 
 template <typename output_t>
@@ -48,18 +49,20 @@ struct shape_consumer_t : shape_options_t
 
     output.init (buffer, font_opts);
   }
-  void consume_line (const char   *text,
-		     unsigned int  text_len,
-		     const char   *text_before,
-		     const char   *text_after)
+  bool consume_line (shape_text_options_t &text_opts)
   {
+    unsigned int text_len;
+    const char *text;
+    if (!(text = text_opts.get_line (&text_len)))
+      return false;
+
     output.new_line ();
 
     for (unsigned int n = num_iterations; n; n--)
     {
       const char *error = nullptr;
 
-      populate_buffer (buffer, text, text_len, text_before, text_after);
+      populate_buffer (buffer, text, text_len, text_opts.text_before, text_opts.text_after);
       if (n == 1)
 	output.consume_text (buffer, text, text_len, utf8_clusters);
       if (!shape (font, buffer, &error))
@@ -69,11 +72,12 @@ struct shape_consumer_t : shape_options_t
 	if (hb_buffer_get_content_type (buffer) == HB_BUFFER_CONTENT_TYPE_GLYPHS)
 	  break;
 	else
-	  return;
+	  return true;
       }
     }
 
     output.consume_glyphs (buffer, text, text_len, utf8_clusters);
+    return true;
   }
   void finish (const font_options_t *font_opts)
   {
diff --git a/util/text-options.hh b/util/text-options.hh
index 8f76612b0..9ed47fd7e 100644
--- a/util/text-options.hh
+++ b/util/text-options.hh
@@ -1,3 +1,33 @@
+/*
+ * Copyright © 2011  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 TEXT_OPTIONS_HH
+#define TEXT_OPTIONS_HH
+
+#include "options.hh"
 
 struct text_options_t
 {
@@ -6,8 +36,6 @@ struct text_options_t
   {}
   ~text_options_t ()
   {
-    g_free (text_before);
-    g_free (text_after);
     g_free (text);
     g_free (text_file);
     if (gs)
@@ -47,9 +75,6 @@ struct text_options_t
 
   const char *get_line (unsigned int *len);
 
-  char *text_before = nullptr;
-  char *text_after = nullptr;
-
   int text_len = -1;
   char *text = nullptr;
   char *text_file = nullptr;
@@ -59,6 +84,20 @@ struct text_options_t
   GString *gs = nullptr;
 };
 
+struct shape_text_options_t : text_options_t
+{
+  ~shape_text_options_t ()
+  {
+    g_free (text_before);
+    g_free (text_after);
+  }
+
+  void add_options (option_parser_t *parser);
+
+  char *text_before = nullptr;
+  char *text_after = nullptr;
+};
+
 
 static gboolean
 parse_text (const char *name G_GNUC_UNUSED,
@@ -182,9 +221,7 @@ text_options_t::add_options (option_parser_t *parser)
   {
     {"text",		0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_text,		"Set input text",			"string"},
     {"text-file",	0, 0, G_OPTION_ARG_STRING,	&this->text_file,		"Set input text file-name",		"filename"},
-    {"unicodes",      'u', 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_unicodes,	"Set input Unicode codepoints\n\n    If no text is provided, standard input is used for input.\n",		"list of hex numbers"},
-    {"text-before",	0, 0, G_OPTION_ARG_STRING,	&this->text_before,		"Set text context before each line",	"string"},
-    {"text-after",	0, 0, G_OPTION_ARG_STRING,	&this->text_after,		"Set text context after each line",	"string"},
+    {"unicodes",      'u', 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_unicodes,	"Set input Unicode codepoints\n\n    If no text is provided, standard input is used for input.",		"list of hex numbers"},
     {nullptr}
   };
   parser->add_group (entries,
@@ -193,3 +230,23 @@ text_options_t::add_options (option_parser_t *parser)
 		     "Options for the input text",
 		     this);
 }
+
+void
+shape_text_options_t::add_options (option_parser_t *parser)
+{
+  text_options_t::add_options (parser);
+
+  GOptionEntry entries[] =
+  {
+    {"text-before",	0, 0, G_OPTION_ARG_STRING,	&this->text_before,		"Set text context before each line",	"string"},
+    {"text-after",	0, 0, G_OPTION_ARG_STRING,	&this->text_after,		"Set text context after each line",	"string"},
+    {nullptr}
+  };
+  parser->add_group (entries,
+		     "text-context",
+		     "Textual context options:",
+		     "Options for the input context text",
+		     this);
+}
+
+#endif