| Index: third_party/harfbuzz-ng/src/hb-ot-font.cc
|
| diff --git a/third_party/harfbuzz-ng/src/hb-ot-font.cc b/third_party/harfbuzz-ng/src/hb-ot-font.cc
|
| index 3514fcc27be88f246fb8687c6d651e98031f7425..2af2f54a75932abf0232fdbadae2a02dc5068f6f 100644
|
| --- a/third_party/harfbuzz-ng/src/hb-ot-font.cc
|
| +++ b/third_party/harfbuzz-ng/src/hb-ot-font.cc
|
| @@ -35,17 +35,128 @@
|
| #include "hb-ot-hmtx-table.hh"
|
|
|
|
|
| +struct hb_ot_face_metrics_accelerator_t
|
| +{
|
| + unsigned int num_metrics;
|
| + unsigned int num_advances;
|
| + unsigned int default_advance;
|
| + const OT::_mtx *table;
|
| + hb_blob_t *blob;
|
| +
|
| + inline void init (hb_face_t *face,
|
| + hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
|
| + unsigned int default_advance)
|
| + {
|
| + this->default_advance = default_advance;
|
| + this->num_metrics = face->get_num_glyphs ();
|
| +
|
| + hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
|
| + const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
|
| + this->num_advances = _hea->numberOfLongMetrics;
|
| + hb_blob_destroy (_hea_blob);
|
| +
|
| + this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
|
| + if (unlikely (!this->num_advances ||
|
| + 2 * (this->num_advances + this->num_metrics) < hb_blob_get_length (this->blob)))
|
| + {
|
| + this->num_metrics = this->num_advances = 0;
|
| + hb_blob_destroy (this->blob);
|
| + this->blob = hb_blob_get_empty ();
|
| + }
|
| + this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
|
| + }
|
| +
|
| + inline void fini (void)
|
| + {
|
| + hb_blob_destroy (this->blob);
|
| + }
|
| +
|
| + inline unsigned int get_advance (hb_codepoint_t glyph) const
|
| + {
|
| + if (unlikely (glyph >= this->num_metrics))
|
| + {
|
| + /* If this->num_metrics is zero, it means we don't have the metrics table
|
| + * for this direction: return one EM. Otherwise, it means that the glyph
|
| + * index is out of bound: return zero. */
|
| + if (this->num_metrics)
|
| + return 0;
|
| + else
|
| + return this->default_advance;
|
| + }
|
| +
|
| + if (glyph >= this->num_advances)
|
| + glyph = this->num_advances - 1;
|
| +
|
| + return this->table->longMetric[glyph].advance;
|
| + }
|
| +};
|
| +
|
| +struct hb_ot_face_cmap_accelerator_t
|
| +{
|
| + const OT::CmapSubtable *table;
|
| + const OT::CmapSubtable *uvs_table;
|
| + hb_blob_t *blob;
|
| +
|
| + inline void init (hb_face_t *face)
|
| + {
|
| + this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
|
| + const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
|
| + const OT::CmapSubtable *subtable = NULL;
|
| + const OT::CmapSubtable *subtable_uvs = NULL;
|
| +
|
| + /* 32-bit subtables. */
|
| + if (!subtable) subtable = cmap->find_subtable (3, 10);
|
| + if (!subtable) subtable = cmap->find_subtable (0, 6);
|
| + if (!subtable) subtable = cmap->find_subtable (0, 4);
|
| + /* 16-bit subtables. */
|
| + if (!subtable) subtable = cmap->find_subtable (3, 1);
|
| + if (!subtable) subtable = cmap->find_subtable (0, 3);
|
| + if (!subtable) subtable = cmap->find_subtable (0, 2);
|
| + if (!subtable) subtable = cmap->find_subtable (0, 1);
|
| + if (!subtable) subtable = cmap->find_subtable (0, 0);
|
| + /* Meh. */
|
| + if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
|
| +
|
| + /* UVS subtable. */
|
| + if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
|
| + /* Meh. */
|
| + if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
|
| +
|
| + this->table = subtable;
|
| + this->uvs_table = subtable_uvs;
|
| + }
|
| +
|
| + inline void fini (void)
|
| + {
|
| + hb_blob_destroy (this->blob);
|
| + }
|
| +
|
| + inline bool get_glyph (hb_codepoint_t unicode,
|
| + hb_codepoint_t variation_selector,
|
| + hb_codepoint_t *glyph) const
|
| + {
|
| + if (unlikely (variation_selector))
|
| + {
|
| + switch (this->uvs_table->get_glyph_variant (unicode,
|
| + variation_selector,
|
| + glyph))
|
| + {
|
| + case OT::GLYPH_VARIANT_NOT_FOUND: return false;
|
| + case OT::GLYPH_VARIANT_FOUND: return true;
|
| + case OT::GLYPH_VARIANT_USE_DEFAULT: break;
|
| + }
|
| + }
|
| +
|
| + return this->table->get_glyph (unicode, glyph);
|
| + }
|
| +};
|
| +
|
|
|
| struct hb_ot_font_t
|
| {
|
| - unsigned int num_glyphs;
|
| - unsigned int num_hmetrics;
|
| - const OT::hmtx *hmtx;
|
| - hb_blob_t *hmtx_blob;
|
| -
|
| - const OT::CmapSubtable *cmap;
|
| - const OT::CmapSubtable *cmap_uvs;
|
| - hb_blob_t *cmap_blob;
|
| + hb_ot_face_cmap_accelerator_t cmap;
|
| + hb_ot_face_metrics_accelerator_t h_metrics;
|
| + hb_ot_face_metrics_accelerator_t v_metrics;
|
| };
|
|
|
|
|
| @@ -53,53 +164,16 @@ static hb_ot_font_t *
|
| _hb_ot_font_create (hb_font_t *font)
|
| {
|
| hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
|
| + hb_face_t *face = font->face;
|
|
|
| if (unlikely (!ot_font))
|
| return NULL;
|
|
|
| - ot_font->num_glyphs = font->face->get_num_glyphs ();
|
| + unsigned int upem = face->get_upem ();
|
|
|
| - {
|
| - hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
|
| - const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
|
| - ot_font->num_hmetrics = hhea->numberOfHMetrics;
|
| - hb_blob_destroy (hhea_blob);
|
| - }
|
| - ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx));
|
| - if (unlikely (!ot_font->num_hmetrics ||
|
| - 2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob)))
|
| - {
|
| - hb_blob_destroy (ot_font->hmtx_blob);
|
| - free (ot_font);
|
| - return NULL;
|
| - }
|
| - ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
|
| -
|
| - ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap));
|
| - const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (ot_font->cmap_blob);
|
| - const OT::CmapSubtable *subtable = NULL;
|
| - const OT::CmapSubtable *subtable_uvs = NULL;
|
| -
|
| - /* 32-bit subtables. */
|
| - if (!subtable) subtable = cmap->find_subtable (3, 10);
|
| - if (!subtable) subtable = cmap->find_subtable (0, 6);
|
| - if (!subtable) subtable = cmap->find_subtable (0, 4);
|
| - /* 16-bit subtables. */
|
| - if (!subtable) subtable = cmap->find_subtable (3, 1);
|
| - if (!subtable) subtable = cmap->find_subtable (0, 3);
|
| - if (!subtable) subtable = cmap->find_subtable (0, 2);
|
| - if (!subtable) subtable = cmap->find_subtable (0, 1);
|
| - if (!subtable) subtable = cmap->find_subtable (0, 0);
|
| - /* Meh. */
|
| - if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
|
| -
|
| - /* UVS subtable. */
|
| - if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
|
| - /* Meh. */
|
| - if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
|
| -
|
| - ot_font->cmap = subtable;
|
| - ot_font->cmap_uvs = subtable_uvs;
|
| + ot_font->cmap.init (face);
|
| + ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
|
| + ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */
|
|
|
| return ot_font;
|
| }
|
| @@ -107,8 +181,9 @@ _hb_ot_font_create (hb_font_t *font)
|
| static void
|
| _hb_ot_font_destroy (hb_ot_font_t *ot_font)
|
| {
|
| - hb_blob_destroy (ot_font->cmap_blob);
|
| - hb_blob_destroy (ot_font->hmtx_blob);
|
| + ot_font->cmap.fini ();
|
| + ot_font->h_metrics.fini ();
|
| + ot_font->v_metrics.fini ();
|
|
|
| free (ot_font);
|
| }
|
| @@ -124,20 +199,7 @@ hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
|
|
|
| {
|
| const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
| -
|
| - if (unlikely (variation_selector))
|
| - {
|
| - switch (ot_font->cmap_uvs->get_glyph_variant (unicode,
|
| - variation_selector,
|
| - glyph))
|
| - {
|
| - case OT::GLYPH_VARIANT_NOT_FOUND: return false;
|
| - case OT::GLYPH_VARIANT_FOUND: return true;
|
| - case OT::GLYPH_VARIANT_USE_DEFAULT: break;
|
| - }
|
| - }
|
| -
|
| - return ot_font->cmap->get_glyph (unicode, glyph);
|
| + return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
|
| }
|
|
|
| static hb_position_t
|
| @@ -147,14 +209,7 @@ hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
|
| void *user_data HB_UNUSED)
|
| {
|
| const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
| -
|
| - if (unlikely (glyph >= ot_font->num_glyphs))
|
| - return 0; /* Maybe better to return notdef's advance instead? */
|
| -
|
| - if (glyph >= ot_font->num_hmetrics)
|
| - glyph = ot_font->num_hmetrics - 1;
|
| -
|
| - return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth);
|
| + return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
|
| }
|
|
|
| static hb_position_t
|
| @@ -163,8 +218,8 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
|
| hb_codepoint_t glyph,
|
| void *user_data HB_UNUSED)
|
| {
|
| - /* TODO */
|
| - return 0;
|
| + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
| + return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph));
|
| }
|
|
|
| static hb_bool_t
|
| @@ -209,6 +264,7 @@ hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
|
| hb_codepoint_t bottom_glyph HB_UNUSED,
|
| void *user_data HB_UNUSED)
|
| {
|
| + /* OpenType doesn't have vertical-kerning other than GPOS. */
|
| return 0;
|
| }
|
|
|
|
|