From 4a5bd7a9267973c134c3fe1198d8cf8cf94cb4f1 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad@behdad.org>
Date: Sun, 1 Jan 2023 16:53:28 -0700
Subject: [PATCH] [subset] Add hb_subset_input_keep_everything()

Fixes https://github.com/harfbuzz/harfbuzz/issues/3998

New API:
+ hb_subset_input_keep_everything()
---
 docs/harfbuzz-sections.txt |  1 +
 src/hb-subset-input.cc     | 56 +++++++++++++++++++++++++-------------
 src/hb-subset.h            |  3 ++
 util/hb-subset.cc          | 15 ++++++++++
 4 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index a9846f891..f697157ae 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -846,6 +846,7 @@ hb_subset_input_reference
 hb_subset_input_destroy
 hb_subset_input_set_user_data
 hb_subset_input_get_user_data
+hb_subset_input_keep_everything
 hb_subset_input_set_flags
 hb_subset_input_get_flags
 hb_subset_input_unicode_set
diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc
index 5752b2297..bad4553ea 100644
--- a/src/hb-subset-input.cc
+++ b/src/hb-subset-input.cc
@@ -395,6 +395,42 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input,
   return hb_object_get_user_data (input, key);
 }
 
+/**
+ * hb_subset_input_keep_everything:
+ * @input: a #hb_subset_input_t object
+ *
+ * Configure input object to keep everything in the font face.
+ * That is, all Unicodes, glyphs, names, layout items,
+ * glyph names, etc.
+ *
+ * The input can be tailored afterwards by the caller.
+ *
+ * Since: REPLACEME
+ */
+void
+hb_subset_input_keep_everything (hb_subset_input_t *input)
+{
+  const hb_subset_sets_t indices[] = {HB_SUBSET_SETS_UNICODE,
+				      HB_SUBSET_SETS_GLYPH_INDEX,
+				      HB_SUBSET_SETS_NAME_ID,
+				      HB_SUBSET_SETS_NAME_LANG_ID,
+				      HB_SUBSET_SETS_LAYOUT_FEATURE_TAG,
+				      HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG};
+
+  for (auto idx : hb_iter (indices))
+  {
+    hb_set_t *set = hb_subset_input_set (input, idx);
+    hb_set_clear (set);
+    hb_set_invert (set);
+  }
+
+  hb_subset_input_set_flags (input,
+			     HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
+			     HB_SUBSET_FLAGS_GLYPH_NAMES |
+			     HB_SUBSET_FLAGS_RETAIN_GIDS |
+			     HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES);
+}
+
 #ifndef HB_NO_VAR
 /**
  * hb_subset_input_pin_axis_to_default: (skip)
@@ -482,25 +518,7 @@ hb_subset_preprocess (hb_face_t *source)
   if (!input)
     return hb_face_reference (source);
 
-  const hb_subset_sets_t indices[] = {HB_SUBSET_SETS_UNICODE,
-				      HB_SUBSET_SETS_GLYPH_INDEX,
-				      HB_SUBSET_SETS_NAME_ID,
-				      HB_SUBSET_SETS_NAME_LANG_ID,
-				      HB_SUBSET_SETS_LAYOUT_FEATURE_TAG,
-				      HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG};
-
-  for (auto idx : hb_iter (indices))
-  {
-    hb_set_t *set = hb_subset_input_set (input, idx);
-    hb_set_clear (set);
-    hb_set_invert (set);
-  }
-
-  hb_subset_input_set_flags(input,
-                            HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
-                            HB_SUBSET_FLAGS_GLYPH_NAMES |
-                            HB_SUBSET_FLAGS_RETAIN_GIDS |
-                            HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES);
+  hb_subset_input_keep_everything (input);
 
   input->attach_accelerator_data = true;
 
diff --git a/src/hb-subset.h b/src/hb-subset.h
index b83264ea5..ef7d4ba54 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -149,6 +149,9 @@ HB_EXTERN void *
 hb_subset_input_get_user_data (const hb_subset_input_t *input,
 			       hb_user_data_key_t      *key);
 
+HB_EXTERN void
+hb_subset_input_keep_everything (hb_subset_input_t *input);
+
 HB_EXTERN hb_set_t *
 hb_subset_input_unicode_set (hb_subset_input_t *input);
 
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 7b57a2772..20bc17c48 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -528,6 +528,19 @@ parse_name_languages (const char *name,
   return true;
 }
 
+static gboolean
+_keep_everything (const char *name,
+		  const char *arg,
+		  gpointer    data,
+		  GError    **error G_GNUC_UNUSED)
+{
+  subset_main_t *subset_main = (subset_main_t *) data;
+
+  hb_subset_input_keep_everything (subset_main->input);
+
+  return true;
+}
+
 template <hb_subset_flags_t flag>
 static gboolean
 set_flag (const char *name,
@@ -918,6 +931,8 @@ subset_main_t::add_options ()
 
   GOptionEntry flag_entries[] =
   {
+    {"keep-everything",		0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &_keep_everything,
+     "Keep everything by default. Options after this can override the operation.", nullptr},
     {"no-hinting",		0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag<HB_SUBSET_FLAGS_NO_HINTING>,		"Whether to drop hints", nullptr},
     {"retain-gids",		0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag<HB_SUBSET_FLAGS_RETAIN_GIDS>,		"If set don't renumber glyph ids in the subset.", nullptr},
     {"desubroutinize",		0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag<HB_SUBSET_FLAGS_DESUBROUTINIZE>,		"Remove CFF/CFF2 use of subroutines", nullptr},