Add hb_ot_tags_to_script_and_language
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index 1f526e3..9472af4 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -560,7 +560,8 @@
 HB_OT_TAG_DEFAULT_SCRIPT
 hb_ot_tag_to_language
 hb_ot_tag_to_script
-hb_ot_tags
+hb_ot_tags_from_script_and_language
+hb_ot_tags_to_script_and_language
 </SECTION>
 
 <SECTION>
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 413ec48..45d7dbd 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -59,7 +59,7 @@
   hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
   hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
 
-  hb_ot_tags (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
+  hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
 
   for (unsigned int table_index = 0; table_index < 2; table_index++) {
     hb_tag_t table_tag = table_tags[table_index];
diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc
index 0d4c060..0987fe1 100644
--- a/src/hb-ot-tag.cc
+++ b/src/hb-ot-tag.cc
@@ -121,7 +121,7 @@
 {
   unsigned int count = 2;
   hb_tag_t tags[2];
-  hb_ot_tags (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr);
+  hb_ot_tags_from_script_and_language (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr);
   *script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT;
   *script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT;
 }
@@ -231,7 +231,7 @@
 {
   unsigned int count = 1;
   hb_tag_t tags[1];
-  hb_ot_tags (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
+  hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
   return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE;
 }
 
@@ -307,6 +307,8 @@
 	for (; i < 4; i++)
 	  tag[i] = ' ';
 	tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
+	if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
+	  tags[0] ^= ~0xDFDFDFDF;
 	*count = 1;
 	return false;
       }
@@ -316,7 +318,7 @@
 }
 
 /**
- * hb_ot_tags:
+ * hb_ot_tags_from_script_and_language:
  * @script: an #hb_script_t to convert.
  * @language: an #hb_language_t to convert.
  * @script_count: (allow-none): maximum number of script tags to retrieve (IN)
@@ -332,12 +334,12 @@
  *
  **/
 void
-hb_ot_tags (hb_script_t   script,
-	    hb_language_t language,
-	    unsigned int *script_count /* IN/OUT */,
-	    hb_tag_t     *script_tags /* OUT */,
-	    unsigned int *language_count /* IN/OUT */,
-	    hb_tag_t     *language_tags /* OUT */)
+hb_ot_tags_from_script_and_language (hb_script_t   script,
+				     hb_language_t language,
+				     unsigned int *script_count /* IN/OUT */,
+				     hb_tag_t     *script_tags /* OUT */,
+				     unsigned int *language_count /* IN/OUT */,
+				     hb_tag_t     *language_tags /* OUT */)
 {
   bool needs_script = true;
 
@@ -428,6 +430,61 @@
   }
 }
 
+/**
+ * hb_ot_tags_to_script_and_language:
+ * @script_tag: a script tag
+ * @language_tag: a language tag
+ * @script (allow-none): the #hb_script_t corresponding to @script_tag (OUT).
+ * @language (allow-none): the #hb_language_t corresponding to @script_tag and
+ * @language_tag (OUT).
+ *
+ * Converts a script tag and a language tag to an #hb_script_t and an
+ * #hb_language_t.
+ *
+ **/
+void
+hb_ot_tags_to_script_and_language (hb_tag_t       script_tag,
+				   hb_tag_t       language_tag,
+				   hb_script_t   *script /* OUT */,
+				   hb_language_t *language /* OUT */)
+{
+  hb_script_t script_out = hb_ot_tag_to_script (script_tag);
+  if (script)
+    *script = script_out;
+  if (language) {
+    unsigned int script_count = 1;
+    hb_tag_t primary_script_tag[1];
+    hb_ot_tags_from_script_and_language (script_out, HB_LANGUAGE_INVALID, &script_count, primary_script_tag, nullptr, nullptr);
+    *language = hb_ot_tag_to_language (language_tag);
+    if (script_count == 0 || primary_script_tag[0] != script_tag) {
+      unsigned char *buf;
+      const char *lang_str = hb_language_to_string (*language);
+      size_t len = strlen (lang_str);
+      buf = (unsigned char *) malloc (len + 11);
+      if (unlikely (!buf)) {
+	*language = nullptr;
+      } else {
+	memcpy (buf, lang_str, len);
+	if (lang_str[0] != 'x' || lang_str[1] != '-') {
+	  buf[len++] = '-';
+	  buf[len++] = 'x';
+	}
+	buf[len++] = '-';
+	buf[len++] = 'h';
+	buf[len++] = 'b';
+	buf[len++] = 's';
+	buf[len++] = 'c';
+	buf[len++] = script_tag >> 24;
+	buf[len++] = (script_tag >> 16) & 0xFF;
+	buf[len++] = (script_tag >> 8) & 0xFF;
+	buf[len++] = script_tag & 0xFF;
+	*language = hb_language_from_string ((char *) buf, len);
+	free (buf);
+      }
+    }
+  }
+}
+
 #ifdef MAIN
 static inline void
 test_langs_sorted (void)
diff --git a/src/hb-ot-tag.h b/src/hb-ot-tag.h
index ef7014c..e3523a0 100644
--- a/src/hb-ot-tag.h
+++ b/src/hb-ot-tag.h
@@ -43,12 +43,12 @@
 #define HB_OT_MAX_TAGS_PER_LANGUAGE	3u
 
 HB_EXTERN void
-hb_ot_tags (hb_script_t   script,
-	    hb_language_t language,
-	    unsigned int *script_count /* IN/OUT */,
-	    hb_tag_t     *script_tags /* OUT */,
-	    unsigned int *language_count /* IN/OUT */,
-	    hb_tag_t     *language_tags /* OUT */);
+hb_ot_tags_from_script_and_language (hb_script_t   script,
+				     hb_language_t language,
+				     unsigned int *script_count /* IN/OUT */,
+				     hb_tag_t     *script_tags /* OUT */,
+				     unsigned int *language_count /* IN/OUT */,
+				     hb_tag_t     *language_tags /* OUT */);
 
 HB_EXTERN hb_script_t
 hb_ot_tag_to_script (hb_tag_t tag);
@@ -56,6 +56,12 @@
 HB_EXTERN hb_language_t
 hb_ot_tag_to_language (hb_tag_t tag);
 
+HB_EXTERN void
+hb_ot_tags_to_script_and_language (hb_tag_t       script_tag,
+				   hb_tag_t       language_tag,
+				   hb_script_t   *script /* OUT */,
+				   hb_language_t *language /* OUT */);
+
 
 HB_END_DECLS
 
diff --git a/test/api/test-ot-tag.c b/test/api/test-ot-tag.c
index 3502898..6b968bf 100644
--- a/test/api/test-ot-tag.c
+++ b/test/api/test-ot-tag.c
@@ -60,7 +60,7 @@
   g_test_message ("Testing script %c%c%c%c: script tag %s, language tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s, lang_s);
   tag = hb_tag_from_string (s, -1);
 
-  hb_ot_tags (script, hb_language_from_string (lang_s, -1), &count, &t, NULL, NULL);
+  hb_ot_tags_from_script_and_language (script, hb_language_from_string (lang_s, -1), &count, &t, NULL, NULL);
 
   if (count != 0)
   {
@@ -213,6 +213,31 @@
 }
 
 static void
+test_tags_to_script_and_language (const char *script_tag_s,
+				  const char *lang_tag_s,
+				  const char *script_s,
+				  const char *lang_s)
+{
+  hb_script_t actual_script[1];
+  hb_language_t actual_lang[1];
+  hb_tag_t script_tag = hb_tag_from_string (script_tag_s, -1);
+  hb_tag_t lang_tag = hb_tag_from_string (lang_tag_s, -1);
+  hb_ot_tags_to_script_and_language (script_tag, lang_tag, actual_script, actual_lang);
+  g_assert_cmphex (*actual_script, ==, hb_tag_from_string (script_s, -1));
+  g_assert_cmpstr (hb_language_to_string (*actual_lang), ==, lang_s);
+}
+
+static void
+test_ot_tags_to_script_and_language (void)
+{
+  test_tags_to_script_and_language ("DFLT", "ENG", "", "en-x-hbscdflt");
+  test_tags_to_script_and_language ("latn", "ENG", "Latn", "en");
+  test_tags_to_script_and_language ("deva", "MAR", "Deva", "mr-x-hbscdeva");
+  test_tags_to_script_and_language ("dev2", "MAR", "Deva", "mr");
+  test_tags_to_script_and_language ("qaa", "QTZ0", "Qaaa", "x-hbotqtz0-hbscqaa");
+}
+
+static void
 test_ot_tag_language (void)
 {
   g_assert_cmphex (HB_TAG_CHAR4 ("dflt"), ==, HB_OT_TAG_DEFAULT_LANGUAGE);
@@ -406,7 +431,7 @@
   hb_language_t lang = hb_language_from_string (lang_s, -1);
   va_start (expected_tags, expected_language_count);
 
-  hb_ot_tags (script, lang, &script_count, script_tags, &language_count, language_tags);
+  hb_ot_tags_from_script_and_language (script, lang, &script_count, script_tags, &language_count, language_tags);
 
   g_assert_cmpuint (script_count, ==, expected_script_count);
   g_assert_cmpuint (language_count, ==, expected_language_count);
@@ -427,11 +452,13 @@
 test_ot_tag_full (void)
 {
   test_tags (HB_SCRIPT_INVALID, "en", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "ENG");
+  test_tags (HB_SCRIPT_INVALID, "en-x-hbscdflt", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "DFLT", "ENG");
   test_tags (HB_SCRIPT_LATIN, "en", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "latn", "ENG");
   test_tags (HB_SCRIPT_LATIN, "en", 0, 0, 0, 0);
   test_tags (HB_SCRIPT_INVALID, "und-fonnapa", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "APPH");
   test_tags (HB_SCRIPT_INVALID, "en-fonnapa", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "APPH");
   test_tags (HB_SCRIPT_INVALID, "x-hbot1234-hbsc5678", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
+  test_tags (HB_SCRIPT_INVALID, "x-hbsc5678-hbot1234", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
   test_tags (HB_SCRIPT_MALAYALAM, "ml", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 2, 2, "mlm2", "mlym", "MAL", "MLR");
   test_tags (HB_SCRIPT_MALAYALAM, "ml", 1, 1, 1, 1, "mlm2", "MAL");
   test_tags (HB_SCRIPT_INVALID, "xyz", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "XYZ");
@@ -448,6 +475,8 @@
   hb_test_add (test_ot_tag_script_from_language);
   hb_test_add (test_ot_tag_script_indic);
 
+  hb_test_add (test_ot_tags_to_script_and_language);
+
   hb_test_add (test_ot_tag_language);
 
   hb_test_add (test_ot_tag_full);