Add a new API, hb_ot_layout_get_feature_name_ids (#976)
This new API returns cvXX and ssXX related NameId, things like
featUiLabelNameId, featUiTooltipTextNameId, sampleTextNameId, ... of cvXX
and UINameId of ssXX, in a unified way.
However HarfBuzz currently doesn't expose an API for retrieving the actual
information associated with NameId from the `name` table and that should be
done separately.
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index 5715d77..b93cd1d 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -450,6 +450,7 @@
hb_ot_layout_feature_get_lookups
hb_ot_layout_feature_with_variations_get_lookups
hb_ot_layout_get_attach_points
+hb_ot_layout_get_feature_name_ids
hb_ot_layout_get_glyph_class
hb_ot_layout_get_glyphs_in_class
hb_ot_layout_get_ligature_carets
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 2ae1157..21caf9e 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -478,6 +478,20 @@
return Null(FeatureParamsSize);
}
+ inline const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
+ {
+ if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+ return u.stylisticSet;
+ return Null(FeatureParamsStylisticSet);
+ }
+
+ inline const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
+ {
+ if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+ return u.characterVariants;
+ return Null(FeatureParamsCharacterVariants);
+ }
+
private:
union {
FeatureParamsSize size;
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 3a08230..3bfa191 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1016,6 +1016,24 @@
OT::GPOS::position_finish_offsets (font, buffer);
}
+static const OT::FeatureParams&
+_get_gsubgpos_matched_feature_params (hb_face_t *face, hb_tag_t feature)
+{
+ const OT::GSUB &gsub = _get_gsub (face);
+ unsigned int gsub_num_features = gsub.get_feature_count ();
+ for (unsigned int i = 0; i < gsub_num_features; i++)
+ if (feature == gsub.get_feature_tag (i))
+ return gsub.get_feature (i).get_feature_params ();
+
+ const OT::GPOS &gpos = _get_gpos (face);
+ unsigned int gpos_num_features = gpos.get_feature_count ();
+ for (unsigned int i = 0; i < gpos_num_features; i++)
+ if (feature == gpos.get_feature_tag (i))
+ return gpos.get_feature (i).get_feature_params ();
+
+ return Null (OT::FeatureParams);
+}
+
/**
* hb_ot_layout_get_size_params:
*
@@ -1066,6 +1084,74 @@
return false;
}
+/**
+ * hb_ot_layout_get_feature_name_ids:
+ * @face: #hb_face_t to work upon
+ * @feature: ssXX and cvXX tag
+ * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ * for a user-interface label for this feature. (May be NULL.)
+ * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ * that an application can use for tooltip text for this
+ * feature. (May be NULL.)
+ * @sample_id: (out) (allow-none): The ‘name’ table name ID that specifies sample text
+ * that illustrates the effect of this feature. (May be NULL.)
+ * @num_named_parameters: (out) (allow-none): Number of named parameters. (May be zero.)
+ * @first_param_id: (out) (allow-none): The first ‘name’ table name ID used to specify
+ * strings for user-interface labels for the feature
+ * parameters. (Must be zero if numParameters is zero.)
+ *
+ * Return value: true if could find any feature with the tag, false otherwise
+ *
+ * Since: REPLACEME
+ **/
+hb_bool_t
+hb_ot_layout_get_feature_name_ids (hb_face_t *face,
+ hb_tag_t feature,
+ unsigned int *label_id, /* OUT. May be nullptr */
+ unsigned int *tooltip_id, /* OUT. May be nullptr */
+ unsigned int *sample_id, /* OUT. May be nullptr */
+ unsigned int *num_named_parameters, /* OUT. May be nullptr */
+ unsigned int *first_param_id /* OUT. May be nullptr */)
+{
+ const OT::FeatureParams &feature_params =
+ _get_gsubgpos_matched_feature_params (face, feature);
+ if (&feature_params != &Null (OT::FeatureParams))
+ {
+ const OT::FeatureParamsStylisticSet& ss_params =
+ feature_params.get_stylistic_set_params (feature);
+ if (&ss_params != &Null (OT::FeatureParamsStylisticSet)) /* ssXX */
+ {
+#define PARAM(a, A) if (a) *a = A
+ PARAM(label_id, ss_params.uiNameID);
+ // ssXX features don't have the rest
+ PARAM(tooltip_id, 0);
+ PARAM(sample_id, 0);
+ PARAM(num_named_parameters, 0);
+ PARAM(first_param_id, 0);
+ return true;
+ }
+ const OT::FeatureParamsCharacterVariants& cv_params =
+ feature_params.get_character_variants_params (feature);
+ if (&cv_params != &Null (OT::FeatureParamsCharacterVariants)) /* cvXX */
+ {
+ PARAM(label_id, cv_params.featUILableNameID);
+ PARAM(tooltip_id, cv_params.featUITooltipTextNameID);
+ PARAM(sample_id, cv_params.sampleTextNameID);
+ PARAM(num_named_parameters, cv_params.numNamedParameters);
+ PARAM(first_param_id, cv_params.firstParamUILabelNameID);
+ return true;
+ }
+ }
+
+ PARAM(label_id, 0);
+ PARAM(tooltip_id, 0);
+ PARAM(sample_id, 0);
+ PARAM(num_named_parameters, 0);
+ PARAM(first_param_id, 0);
+#undef PARAM
+ return false;
+}
+
/*
* Parts of different types are implemented here such that they have direct
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 0278796..f859767 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -322,6 +322,14 @@
unsigned int *range_start, /* OUT. May be NULL */
unsigned int *range_end /* OUT. May be NULL */);
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_feature_name_ids (hb_face_t *face,
+ hb_tag_t feature,
+ unsigned int *label_id /* OUT. May be NULL */,
+ unsigned int *tooltip_id /* OUT. May be NULL */,
+ unsigned int *sample_id /* OUT. May be NULL */,
+ unsigned int *num_named_parameters /* OUT. May be NULL */,
+ unsigned int *first_param_id /* OUT. May be NULL */);
/*
* BASE