summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/hb-ot-layout.cc
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-ot-layout.cc')
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc407
1 files changed, 353 insertions, 54 deletions
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index a599eea6e9..f9c0daa486 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc
@@ -46,7 +46,7 @@
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
-#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-layout-base-table.hh"
#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-name-table.hh"
#include "hb-ot-os2-table.hh"
@@ -54,6 +54,9 @@
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
+
/**
* SECTION:hb-ot-layout
* @title: hb-ot-layout
@@ -76,7 +79,7 @@
* Tests whether a face includes any kerning data in the 'kern' table.
* Does NOT test for kerning lookups in the GPOS table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
bool
@@ -92,7 +95,7 @@ hb_ot_layout_has_kerning (hb_face_t *face)
* Tests whether a face includes any state-machine kerning in the 'kern' table.
* Does NOT examine the GPOS table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
bool
@@ -112,7 +115,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face)
*
* Does NOT examine the GPOS table.
*
- * Return value: %true is data found, %false otherwise
+ * Return value: `true` is data found, `false` otherwise
*
**/
bool
@@ -258,7 +261,6 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
{
_hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
_hb_glyph_info_clear_lig_props (&buffer->info[i]);
- buffer->info[i].syllable() = 0;
}
}
@@ -270,7 +272,7 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
*
* Tests whether a face has any glyph classes defined in its GDEF table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
hb_bool_t
@@ -361,6 +363,13 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
* Fetches a list of the caret positions defined for a ligature glyph in the GDEF
* table of the font. The list returned will begin at the offset provided.
*
+ * Note that a ligature that is formed from n characters will have n-1
+ * caret positions. The first character is not represented in the array,
+ * since its caret position is the glyph position.
+ *
+ * The positions returned by this function are 'unshaped', and will have to
+ * be fixed up for kerning that may be applied to the ligature glyph.
+ *
* Return value: Total number of ligature caret positions for @glyph.
*
**/
@@ -382,7 +391,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
*/
bool
-OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
+GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
hb_face_t *face) const
{
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
@@ -392,7 +401,7 @@ OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
}
bool
-OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
+GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
hb_face_t *face HB_UNUSED) const
{
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
@@ -452,7 +461,7 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face,
* Fetches the index if a given script tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the script is found, %false otherwise
+ * Return value: `true` if the script is found, `false` otherwise
*
**/
hb_bool_t
@@ -526,7 +535,7 @@ hb_ot_layout_table_choose_script (hb_face_t *face,
* #HB_OT_LAYOUT_NO_SCRIPT_INDEX.
*
* Return value:
- * %true if one of the requested scripts is selected, %false if a fallback
+ * `true` if one of the requested scripts is selected, `false` if a fallback
* script is selected or if no scripts are selected.
*
* Since: 2.0.0
@@ -619,7 +628,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
* Fetches the index for a given feature tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
**/
bool
hb_ot_layout_table_find_feature (hb_face_t *face,
@@ -686,7 +695,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
* Fetches the index of a given language tag in the specified face's GSUB table
* or GPOS table, underneath the specified script tag.
*
- * Return value: %true if the language tag is found, %false otherwise
+ * Return value: `true` if the language tag is found, `false` otherwise
*
* Since: 0.6.0
* Deprecated: 2.0.0
@@ -721,10 +730,10 @@ hb_ot_layout_script_find_language (hb_face_t *face,
* in the specified face's GSUB or GPOS table, underneath the specified script
* index.
*
- * If none of the given language tags is found, %false is returned and
+ * If none of the given language tags is found, `false` is returned and
* @language_index is set to the default language index.
*
- * Return value: %true if one of the given language tags is found, %false otherwise
+ * Return value: `true` if one of the given language tags is found, `false` otherwise
*
* Since: 2.0.0
**/
@@ -767,7 +776,7 @@ hb_ot_layout_script_select_language (hb_face_t *face,
* Fetches the index of a requested feature in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
**/
hb_bool_t
@@ -798,7 +807,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
* Fetches the tag of a requested feature index in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
* Since: 0.9.30
**/
@@ -908,7 +917,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
* Fetches the index of a given feature tag in the specified face's GSUB table
* or GPOS table, underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
**/
hb_bool_t
@@ -999,7 +1008,7 @@ struct hb_collect_features_context_t
hb_collect_features_context_t (hb_face_t *face,
hb_tag_t table_tag,
hb_set_t *feature_indices_,
- const hb_tag_t *features)
+ const hb_tag_t *features)
: g (get_gsubgpos_table (face, table_tag)),
feature_indices (feature_indices_),
@@ -1026,7 +1035,7 @@ struct hb_collect_features_context_t
{
hb_tag_t tag = g.get_feature_tag (i);
if (features_set.has (tag))
- feature_indices_filter.add(i);
+ feature_indices_filter.add(i);
}
}
@@ -1305,7 +1314,7 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
* Fetches a list of feature variations in the specified face's GSUB table
* or GPOS table, at the specified variation coordinates.
*
- * Return value: %true if feature variations were found, %false otherwise.
+ * Return value: `true` if feature variations were found, `false` otherwise.
*
**/
hb_bool_t
@@ -1368,7 +1377,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
*
* Tests whether the specified face includes any GSUB substitutions.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
hb_bool_t
@@ -1390,7 +1399,7 @@ hb_ot_layout_has_substitution (hb_face_t *face)
* Tests whether a specified lookup in the specified face would
* trigger a substitution on the given glyph sequence.
*
- * Return value: %true if a substitution would be triggered, %false otherwise
+ * Return value: `true` if a substitution would be triggered, `false` otherwise
*
* Since: 0.9.7
**/
@@ -1492,15 +1501,12 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
l.closure (&c, lookup_index);
-
- for (auto _ : done_lookups_glyph_set.iter ())
- hb_set_destroy (_.second);
}
/**
@@ -1520,9 +1526,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
- const OT::GSUB& gsub = *face->table.GSUB->table;
+ const GSUB& gsub = *face->table.GSUB->table;
unsigned int iteration_count = 0;
unsigned int glyphs_length;
@@ -1542,13 +1548,10 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
}
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
glyphs_length != glyphs->get_population ());
-
- for (auto _ : done_lookups_glyph_set.iter ())
- hb_set_destroy (_.second);
}
/*
- * OT::GPOS
+ * GPOS
*/
@@ -1558,7 +1561,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
*
* Tests whether the specified face includes any GPOS positioning.
*
- * Return value: %true if the face has GPOS data, %false otherwise
+ * Return value: `true` if the face has GPOS data, `false` otherwise
*
**/
hb_bool_t
@@ -1579,7 +1582,7 @@ hb_ot_layout_has_positioning (hb_face_t *face)
void
hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_start (font, buffer);
+ GPOS::position_start (font, buffer);
}
@@ -1594,7 +1597,7 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
void
hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_finish_advances (font, buffer);
+ GPOS::position_finish_advances (font, buffer);
}
/**
@@ -1608,7 +1611,7 @@ hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
void
hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_finish_offsets (font, buffer);
+ GPOS::position_finish_offsets (font, buffer);
}
@@ -1631,7 +1634,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
* For more information on this distinction, see the [`size` feature documentation](
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size).
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.10
**/
@@ -1643,7 +1646,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *range_start, /* OUT. May be NULL */
unsigned int *range_end /* OUT. May be NULL */)
{
- const OT::GPOS &gpos = *face->table.GPOS->table;
+ const GPOS &gpos = *face->table.GPOS->table;
const hb_tag_t tag = HB_TAG ('s','i','z','e');
unsigned int num_features = gpos.get_feature_count ();
@@ -1695,7 +1698,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
* Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
* "Character Variant" ('cvXX') features.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.0.0
**/
@@ -1794,28 +1797,28 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
struct GSUBProxy
{
static constexpr unsigned table_index = 0u;
- static constexpr bool inplace = false;
+ static constexpr bool always_inplace = false;
typedef OT::SubstLookup Lookup;
GSUBProxy (hb_face_t *face) :
table (*face->table.GSUB->table),
accels (face->table.GSUB->accels) {}
- const OT::GSUB &table;
+ const GSUB &table;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
struct GPOSProxy
{
static constexpr unsigned table_index = 1u;
- static constexpr bool inplace = true;
+ static constexpr bool always_inplace = true;
typedef OT::PosLookup Lookup;
GPOSProxy (hb_face_t *face) :
table (*face->table.GPOS->table),
accels (face->table.GPOS->accels) {}
- const OT::GPOS &table;
+ const GPOS &table;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
@@ -1824,6 +1827,8 @@ static inline bool
apply_forward (OT::hb_ot_apply_context_t *c,
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
+ bool use_cache = accel.cache_enter (c);
+
bool ret = false;
hb_buffer_t *buffer = c->buffer;
while (buffer->idx < buffer->len && buffer->successful)
@@ -1833,7 +1838,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
- applied = accel.apply (c);
+ applied = accel.apply (c, use_cache);
}
if (applied)
@@ -1841,6 +1846,10 @@ apply_forward (OT::hb_ot_apply_context_t *c,
else
(void) buffer->next_glyph ();
}
+
+ if (use_cache)
+ accel.cache_leave (c);
+
return ret;
}
@@ -1855,7 +1864,7 @@ apply_backward (OT::hb_ot_apply_context_t *c,
if (accel.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
- ret |= accel.apply (c);
+ ret |= accel.apply (c, false);
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
@@ -1881,13 +1890,13 @@ apply_string (OT::hb_ot_apply_context_t *c,
if (likely (!lookup.is_reverse ()))
{
/* in/out forward substitution/positioning */
- if (!Proxy::inplace)
+ if (!Proxy::always_inplace)
buffer->clear_output ();
buffer->idx = 0;
apply_forward (c, accel);
- if (!Proxy::inplace)
+ if (!Proxy::always_inplace)
buffer->sync ();
}
else
@@ -1908,7 +1917,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
const unsigned int table_index = proxy.table_index;
unsigned int i = 0;
OT::hb_ot_apply_context_t c (table_index, font, buffer);
- c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
+ c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>);
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
{
@@ -1922,6 +1931,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
c.set_random (lookups[table_index][i].random);
+ c.set_per_syllable (lookups[table_index][i].per_syllable);
apply_string<Proxy> (&c,
proxy.table.get_lookup (lookup_index),
@@ -1960,17 +1970,88 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
#ifndef HB_NO_BASE
/**
+ * hb_ot_layout_get_horizontal_baseline_tag_for_script:
+ * @script: a script tag.
+ *
+ * Fetches the dominant horizontal baseline tag used by @script.
+ *
+ * Return value: dominant baseline tag for the @script.
+ *
+ * Since: 4.0.0
+ **/
+hb_ot_layout_baseline_tag_t
+hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script)
+{
+ /* Keep in sync with hb_ot_layout_get_baseline_with_fallback */
+ switch ((int) script)
+ {
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI:
+ case HB_SCRIPT_DEVANAGARI:
+ case HB_SCRIPT_GUJARATI:
+ case HB_SCRIPT_GURMUKHI:
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN:
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU:
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI:
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA:
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK:
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_SHARADA:
+ case HB_SCRIPT_TAKRI:
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MODI:
+ case HB_SCRIPT_SIDDHAM:
+ case HB_SCRIPT_TIRHUTA:
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_MARCHEN:
+ case HB_SCRIPT_NEWA:
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_SOYOMBO:
+ case HB_SCRIPT_ZANABAZAR_SQUARE:
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA:
+ case HB_SCRIPT_GUNJALA_GONDI:
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_NANDINAGARI:
+ return HB_OT_LAYOUT_BASELINE_TAG_HANGING;
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_HANGUL:
+ case HB_SCRIPT_HAN:
+ case HB_SCRIPT_HIRAGANA:
+ case HB_SCRIPT_KATAKANA:
+ /* Unicode-3.0 additions */
+ case HB_SCRIPT_BOPOMOFO:
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_TANGUT:
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_NUSHU:
+ /* Unicode-13.0 additions */
+ case HB_SCRIPT_KHITAN_SMALL_SCRIPT:
+ return HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT;
+
+ default:
+ return HB_OT_LAYOUT_BASELINE_TAG_ROMAN;
+ }
+}
+
+/**
* hb_ot_layout_get_baseline:
* @font: a font
* @baseline_tag: a baseline tag
* @direction: text direction.
* @script_tag: script tag.
* @language_tag: language tag, currently unused.
- * @coord: (out): baseline value if found.
+ * @coord: (out) (nullable): baseline value if found.
*
* Fetches a baseline value from the face.
*
- * Return value: %true if found baseline value in the font.
+ * Return value: `true` if found baseline value in the font.
*
* Since: 2.6.0
**/
@@ -1982,13 +2063,231 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */)
{
- bool result = font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
+ return font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
+}
+
+/**
+ * hb_ot_layout_get_baseline_with_fallback:
+ * @font: a font
+ * @baseline_tag: a baseline tag
+ * @direction: text direction.
+ * @script_tag: script tag.
+ * @language_tag: language tag, currently unused.
+ * @coord: (out): baseline value if found.
+ *
+ * Fetches a baseline value from the face, and synthesizes
+ * it if the font does not have it.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_position_t *coord /* OUT */)
+{
+ if (hb_ot_layout_get_baseline (font,
+ baseline_tag,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ return;
- if (result && coord)
- *coord = HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (*coord) : font->em_scale_x (*coord);
+ /* Synthesize missing baselines.
+ * See https://www.w3.org/TR/css-inline-3/#baseline-synthesis-fonts
+ */
+ switch (baseline_tag)
+ {
+ case HB_OT_LAYOUT_BASELINE_TAG_ROMAN:
+ *coord = 0; // FIXME origin ?
+ break;
- return result;
+ case HB_OT_LAYOUT_BASELINE_TAG_MATH:
+ {
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+ if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
+ (hb_font_get_nominal_glyph (font, 0x2212u, &glyph) ||
+ hb_font_get_nominal_glyph (font, '-', &glyph)) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ {
+ *coord = extents.y_bearing + extents.height / 2;
+ }
+ else
+ {
+ hb_position_t x_height = font->y_scale / 2;
+#ifndef HB_NO_METRICS
+ hb_ot_metrics_get_position_with_fallback (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height);
+#endif
+ *coord = x_height / 2;
+ }
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT:
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT:
+ {
+ hb_position_t embox_top, embox_bottom;
+
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_bottom);
+
+ if (baseline_tag == HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT)
+ *coord = embox_top + (embox_bottom - embox_top) / 10;
+ else
+ *coord = embox_bottom + (embox_top - embox_bottom) / 10;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT:
+ if (hb_ot_layout_get_baseline (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ *coord += HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
+ else
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, direction, &font_extents);
+ *coord = font_extents.ascender;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT:
+ if (hb_ot_layout_get_baseline (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ *coord -= HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
+ else
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, direction, &font_extents);
+ *coord = font_extents.descender;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_HANGING:
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ {
+ hb_codepoint_t ch;
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+
+ /* Keep in sync with hb_ot_layout_get_horizontal_baseline_for_script */
+ switch ((int) script_tag)
+ {
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI: ch = 0x0995u; break;
+ case HB_SCRIPT_DEVANAGARI: ch = 0x0915u; break;
+ case HB_SCRIPT_GUJARATI: ch = 0x0a95u; break;
+ case HB_SCRIPT_GURMUKHI: ch = 0x0a15u; break;
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN: ch = 0x0f40u; break;
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU: ch = 0x1901u; break;
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI: ch = 0xa807u; break;
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA: ch = 0xa840u; break;
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK: ch = 0xabc0u; break;
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_SHARADA: ch = 0x11191u; break;
+ case HB_SCRIPT_TAKRI: ch = 0x1168cu; break;
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MODI: ch = 0x1160eu;break;
+ case HB_SCRIPT_SIDDHAM: ch = 0x11590u; break;
+ case HB_SCRIPT_TIRHUTA: ch = 0x1148fu; break;
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_MARCHEN: ch = 0x11c72u; break;
+ case HB_SCRIPT_NEWA: ch = 0x1140eu; break;
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_SOYOMBO: ch = 0x11a5cu; break;
+ case HB_SCRIPT_ZANABAZAR_SQUARE: ch = 0x11a0bu; break;
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA: ch = 0x1180au; break;
+ case HB_SCRIPT_GUNJALA_GONDI: ch = 0x11d6cu; break;
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_NANDINAGARI: ch = 0x119b0u; break;
+ default: ch = 0; break;
+ }
+
+ if (ch &&
+ hb_font_get_nominal_glyph (font, ch, &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *coord = extents.y_bearing;
+ else
+ *coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin
+ }
+ else
+ *coord = font->x_scale * 6 / 10; // FIXME makes assumptions about origin
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL:
+ {
+ hb_position_t top, bottom;
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
+ *coord = (top + bottom) / 2;
+
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL:
+ {
+ hb_position_t top, bottom;
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
+ *coord = (top + bottom) / 2;
+
+ }
+ break;
+
+ case _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE:
+ default:
+ *coord = 0;
+ break;
+ }
}
+
#endif