src/hb-ot-font.cc | 208 +++++++++++++++++++++++++++++----------------- src/hb-ot-hhea-table.hh | 63 +++++++------ src/hb-ot-hmtx-table.hh | 35 ++++--- util/helper-cairo-ansi.cc | 4 4 files changed, 189 insertions(+), 121 deletions(-)
New commits: commit 80f77282264afb1356351024b1f062b2824bba3b Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Sep 25 17:59:46 2014 +0300 [util] Fix ansi output when surface is empty diff --git a/util/helper-cairo-ansi.cc b/util/helper-cairo-ansi.cc index 376bf2b..50f9eb4 100644 --- a/util/helper-cairo-ansi.cc +++ b/util/helper-cairo-ansi.cc @@ -63,10 +63,10 @@ helper_cairo_surface_write_to_ansi_stream (cairo_surface_t *surface, * Find the tight image top/bottom and only print in between. */ /* Use corner color as background color. */ - uint32_t bg_color = * (uint32_t *) data; + uint32_t bg_color = data ? * (uint32_t *) data : 0; /* Drop first row while empty */ - while (height) + while (height) { unsigned int i; for (i = 0; i < width; i++) commit 156852991e18e5ac256ee4d6b2916931cc274977 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Sep 25 17:45:49 2014 +0300 [ot-font] Add hb_ot_face_cmap_accelerator_t diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 91df5ca..2af2f54 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -91,14 +91,72 @@ struct hb_ot_face_metrics_accelerator_t } }; +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 { + hb_ot_face_cmap_accelerator_t cmap; hb_ot_face_metrics_accelerator_t h_metrics; hb_ot_face_metrics_accelerator_t v_metrics; - - const OT::CmapSubtable *cmap; - const OT::CmapSubtable *cmap_uvs; - hb_blob_t *cmap_blob; }; @@ -113,35 +171,9 @@ _hb_ot_font_create (hb_font_t *font) unsigned int upem = face->get_upem (); + ot_font->cmap.init (face); ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); - /* TODO Can we do this lazily? */ - ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); - - ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (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->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */ return ot_font; } @@ -149,7 +181,7 @@ _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); + ot_font->cmap.fini (); ot_font->h_metrics.fini (); ot_font->v_metrics.fini (); @@ -167,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 commit d088ccaf11d9475fe0d269ce130b1793b8a1ffbf Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Sep 25 17:26:56 2014 +0300 [ot-font] Minor diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 24de830..91df5ca 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -35,7 +35,7 @@ #include "hb-ot-hmtx-table.hh" -struct metrics_accel_t +struct hb_ot_face_metrics_accelerator_t { unsigned int num_metrics; unsigned int num_advances; @@ -43,19 +43,19 @@ struct metrics_accel_t const OT::_mtx *table; hb_blob_t *blob; - inline void init (hb_font_t *font, + 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 = font->face->get_num_glyphs (); + this->num_metrics = face->get_num_glyphs (); - hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (font->face->reference_table (_hea_tag)); + 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 (font->face->reference_table (_mtx_tag)); + 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))) { @@ -93,8 +93,8 @@ struct metrics_accel_t struct hb_ot_font_t { - metrics_accel_t h_metrics; - metrics_accel_t v_metrics; + hb_ot_face_metrics_accelerator_t h_metrics; + hb_ot_face_metrics_accelerator_t v_metrics; const OT::CmapSubtable *cmap; const OT::CmapSubtable *cmap_uvs; @@ -106,17 +106,18 @@ 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; - unsigned int upem = font->face->get_upem (); + unsigned int upem = face->get_upem (); - ot_font->h_metrics.init (font, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); + ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); /* TODO Can we do this lazily? */ - ot_font->v_metrics.init (font, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); + ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); - ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap)); + ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (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; commit d7c160a1530adabbcf33725b105072293115a34c Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Sep 25 17:15:35 2014 +0300 [ot-font] Handle missing vertical metrics tables diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index d629c41..24de830 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -39,11 +39,15 @@ struct metrics_accel_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_font_t *font, hb_tag_t _hea_tag, hb_tag_t _mtx_tag) + inline void init (hb_font_t *font, + hb_tag_t _hea_tag, hb_tag_t _mtx_tag, + unsigned int default_advance) { + this->default_advance = default_advance; this->num_metrics = font->face->get_num_glyphs (); hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (font->face->reference_table (_hea_tag)); @@ -55,6 +59,7 @@ struct metrics_accel_t 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 (); } @@ -69,7 +74,15 @@ struct metrics_accel_t inline unsigned int get_advance (hb_codepoint_t glyph) const { if (unlikely (glyph >= this->num_metrics)) - return 0; + { + /* 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; @@ -80,8 +93,6 @@ struct metrics_accel_t struct hb_ot_font_t { - unsigned int num_glyphs; - metrics_accel_t h_metrics; metrics_accel_t v_metrics; @@ -99,11 +110,11 @@ _hb_ot_font_create (hb_font_t *font) if (unlikely (!ot_font)) return NULL; - ot_font->num_glyphs = font->face->get_num_glyphs (); + unsigned int upem = font->face->get_upem (); - ot_font->h_metrics.init (font, HB_OT_TAG_hhea, HB_OT_TAG_hmtx); + ot_font->h_metrics.init (font, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); /* TODO Can we do this lazily? */ - ot_font->v_metrics.init (font, HB_OT_TAG_vhea, HB_OT_TAG_vmtx); + ot_font->v_metrics.init (font, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); 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); @@ -233,6 +244,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; } commit be1cca270257bfdfee3fbe821175269713acf408 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Sep 25 16:53:24 2014 +0300 [ot-font] Add metrics_accel_t diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 25fe511..d629c41 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -35,18 +35,55 @@ #include "hb-ot-hmtx-table.hh" +struct metrics_accel_t +{ + unsigned int num_metrics; + unsigned int num_advances; + const OT::_mtx *table; + hb_blob_t *blob; + + inline void init (hb_font_t *font, hb_tag_t _hea_tag, hb_tag_t _mtx_tag) + { + this->num_metrics = font->face->get_num_glyphs (); + + hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (font->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 (font->face->reference_table (_mtx_tag)); + if (unlikely (!this->num_advances || + 2 * (this->num_advances + this->num_metrics) < hb_blob_get_length (this->blob))) + { + 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)) + return 0; + + if (glyph >= this->num_advances) + glyph = this->num_advances - 1; + + return this->table->longMetric[glyph].advance; + } +}; struct hb_ot_font_t { unsigned int num_glyphs; - unsigned int num_hmetrics; - const OT::hmtx *hmtx; - hb_blob_t *hmtx_blob; - - unsigned int num_vmetrics; - const OT::vmtx *vmtx; - hb_blob_t *vmtx_blob; + metrics_accel_t h_metrics; + metrics_accel_t v_metrics; const OT::CmapSubtable *cmap; const OT::CmapSubtable *cmap_uvs; @@ -64,41 +101,9 @@ _hb_ot_font_create (hb_font_t *font) ot_font->num_glyphs = font->face->get_num_glyphs (); - /* Setup horizontal metrics. */ - { - 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->numberOfMetrics; - 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); - } - - /* Setup vertical metrics. */ - { - hb_blob_t *vhea_blob = OT::Sanitizer<OT::vhea>::sanitize (font->face->reference_table (HB_OT_TAG_vhea)); - const OT::vhea *vhea = OT::Sanitizer<OT::vhea>::lock_instance (vhea_blob); - ot_font->num_vmetrics = vhea->numberOfMetrics; - hb_blob_destroy (vhea_blob); - - ot_font->vmtx_blob = OT::Sanitizer<OT::vmtx>::sanitize (font->face->reference_table (HB_TAG('v','m','t','x'))); - if (unlikely (!ot_font->num_vmetrics || - 2 * (ot_font->num_vmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->vmtx_blob))) - { - hb_blob_destroy (ot_font->vmtx_blob); - free (ot_font); - return NULL; - } - ot_font->vmtx = OT::Sanitizer<OT::vmtx>::lock_instance (ot_font->vmtx_blob); - } + ot_font->h_metrics.init (font, HB_OT_TAG_hhea, HB_OT_TAG_hmtx); + /* TODO Can we do this lazily? */ + ot_font->v_metrics.init (font, HB_OT_TAG_vhea, HB_OT_TAG_vmtx); 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); @@ -133,8 +138,8 @@ 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); - hb_blob_destroy (ot_font->vmtx_blob); + ot_font->h_metrics.fini (); + ot_font->v_metrics.fini (); free (ot_font); } @@ -173,14 +178,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; - - if (glyph >= ot_font->num_hmetrics) - glyph = ot_font->num_hmetrics - 1; - - return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advance); + return font->em_scale_x (ot_font->h_metrics.get_advance (glyph)); } static hb_position_t @@ -190,14 +188,7 @@ hb_ot_get_glyph_v_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; - - if (glyph >= ot_font->num_vmetrics) - glyph = ot_font->num_vmetrics - 1; - - return font->em_scale_y (-ot_font->vmtx->longHorMetric[glyph].advance); + return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph)); } static hb_bool_t diff --git a/src/hb-ot-hhea-table.hh b/src/hb-ot-hhea-table.hh index 9999bca..6bf6d5f 100644 --- a/src/hb-ot-hhea-table.hh +++ b/src/hb-ot-hhea-table.hh @@ -80,7 +80,7 @@ struct _hea SHORT reserved3; /* Set to 0. */ SHORT reserved4; /* Set to 0. */ SHORT metricDataFormat; /* 0 for current format. */ - USHORT numberOfMetrics; /* Number of LongMetric entries in metric + USHORT numberOfLongMetrics; /* Number of LongMetric entries in metric * table. */ public: DEFINE_SIZE_STATIC (36); diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index 642c636..932f973 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -63,7 +63,7 @@ struct _mtx } public: - LongMetric longHorMetric[VAR]; /* Paired advance width and leading + LongMetric longMetric[VAR]; /* Paired advance width and leading * bearing values for each glyph. The * value numOfHMetrics comes from * the 'hhea' table. If the font is @@ -85,7 +85,7 @@ struct _mtx * font to vary the side bearing * values for each glyph. */ public: - DEFINE_SIZE_ARRAY2 (0, longHorMetric, leadingBearingX); + DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX); }; struct hmtx : _mtx { commit d41b809e9d21e655129a97c600d28f278fd7e62c Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Sep 25 13:04:08 2014 +0300 [ot-font] Start adding vertical support diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 3514fcc..25fe511 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -39,10 +39,15 @@ struct hb_ot_font_t { unsigned int num_glyphs; + unsigned int num_hmetrics; const OT::hmtx *hmtx; hb_blob_t *hmtx_blob; + unsigned int num_vmetrics; + const OT::vmtx *vmtx; + hb_blob_t *vmtx_blob; + const OT::CmapSubtable *cmap; const OT::CmapSubtable *cmap_uvs; hb_blob_t *cmap_blob; @@ -59,21 +64,41 @@ _hb_ot_font_create (hb_font_t *font) ot_font->num_glyphs = font->face->get_num_glyphs (); + /* Setup horizontal metrics. */ { 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; + ot_font->num_hmetrics = hhea->numberOfMetrics; 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->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))) + + /* Setup vertical metrics. */ { - hb_blob_destroy (ot_font->hmtx_blob); - free (ot_font); - return NULL; + hb_blob_t *vhea_blob = OT::Sanitizer<OT::vhea>::sanitize (font->face->reference_table (HB_OT_TAG_vhea)); + const OT::vhea *vhea = OT::Sanitizer<OT::vhea>::lock_instance (vhea_blob); + ot_font->num_vmetrics = vhea->numberOfMetrics; + hb_blob_destroy (vhea_blob); + + ot_font->vmtx_blob = OT::Sanitizer<OT::vmtx>::sanitize (font->face->reference_table (HB_TAG('v','m','t','x'))); + if (unlikely (!ot_font->num_vmetrics || + 2 * (ot_font->num_vmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->vmtx_blob))) + { + hb_blob_destroy (ot_font->vmtx_blob); + free (ot_font); + return NULL; + } + ot_font->vmtx = OT::Sanitizer<OT::vmtx>::lock_instance (ot_font->vmtx_blob); } - 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); @@ -109,6 +134,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font) { hb_blob_destroy (ot_font->cmap_blob); hb_blob_destroy (ot_font->hmtx_blob); + hb_blob_destroy (ot_font->vmtx_blob); free (ot_font); } @@ -149,12 +175,12 @@ hb_ot_get_glyph_h_advance (hb_font_t *font 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? */ + return 0; 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->hmtx->longHorMetric[glyph].advance); } static hb_position_t @@ -163,8 +189,15 @@ 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; + + if (unlikely (glyph >= ot_font->num_glyphs)) + return 0; + + if (glyph >= ot_font->num_vmetrics) + glyph = ot_font->num_vmetrics - 1; + + return font->em_scale_y (-ot_font->vmtx->longHorMetric[glyph].advance); } static hb_bool_t diff --git a/src/hb-ot-hhea-table.hh b/src/hb-ot-hhea-table.hh index d433200..9999bca 100644 --- a/src/hb-ot-hhea-table.hh +++ b/src/hb-ot-hhea-table.hh @@ -35,14 +35,17 @@ namespace OT { /* * hhea -- The Horizontal Header Table + * vhea -- The Vertical Header Table */ #define HB_OT_TAG_hhea HB_TAG('h','h','e','a') +#define HB_OT_TAG_vhea HB_TAG('v','h','e','a') -struct hhea +struct _hea { - static const hb_tag_t tableTag = HB_OT_TAG_hhea; + static const hb_tag_t hheaTag = HB_OT_TAG_hhea; + static const hb_tag_t vheaTag = HB_OT_TAG_vhea; inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); @@ -51,45 +54,45 @@ struct hhea public: FixedVersion version; /* 0x00010000u for version 1.0. */ - FWORD ascender; /* Typographic ascent. <a - * href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html"> - * (Distance from baseline of highest - * ascender)</a> */ - FWORD descender; /* Typographic descent. <a - * href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html"> - * (Distance from baseline of lowest - * descender)</a> */ - FWORD lineGap; /* Typographic line gap. Negative - * LineGap values are treated as zero - * in Windows 3.1, System 6, and - * System 7. */ - UFWORD advanceWidthMax; /* Maximum advance width value in - * 'hmtx' table. */ - FWORD minLeftSideBearing; /* Minimum left sidebearing value in - * 'hmtx' table. */ - FWORD minRightSideBearing; /* Minimum right sidebearing value; + FWORD ascender; /* Typographic ascent. */ + FWORD descender; /* Typographic descent. */ + FWORD lineGap; /* Typographic line gap. */ + UFWORD advanceMax; /* Maximum advance width/height value in + * metrics table. */ + FWORD minLeadingBearing; /* Minimum left/top sidebearing value in + * metrics table. */ + FWORD minTrailingBearing; /* Minimum right/bottom sidebearing value; * calculated as Min(aw - lsb - - * (xMax - xMin)). */ - FWORD xMaxExtent; /* Max(lsb + (xMax - xMin)). */ + * (xMax - xMin)) for horizontal. */ + FWORD maxExtent; /* horizontal: Max(lsb + (xMax - xMin)), + * vertical: minLeadingBearing+(yMax-yMin). */ SHORT caretSlopeRise; /* Used to calculate the slope of the - * cursor (rise/run); 1 for vertical. */ - SHORT caretSlopeRun; /* 0 for vertical. */ + * cursor (rise/run); 1 for vertical caret, + * 0 for horizontal.*/ + SHORT caretSlopeRun; /* 0 for vertical caret, 1 for horizontal. */ SHORT caretOffset; /* The amount by which a slanted * highlight on a glyph needs * to be shifted to produce the * best appearance. Set to 0 for - * non--slanted fonts */ - SHORT reserved1; /* set to 0 */ - SHORT reserved2; /* set to 0 */ - SHORT reserved3; /* set to 0 */ - SHORT reserved4; /* set to 0 */ + * non-slanted fonts. */ + SHORT reserved1; /* Set to 0. */ + SHORT reserved2; /* Set to 0. */ + SHORT reserved3; /* Set to 0. */ + SHORT reserved4; /* Set to 0. */ SHORT metricDataFormat; /* 0 for current format. */ - USHORT numberOfHMetrics; /* Number of hMetric entries in 'hmtx' - * table */ + USHORT numberOfMetrics; /* Number of LongMetric entries in metric + * table. */ public: DEFINE_SIZE_STATIC (36); }; +struct hhea : _hea { + static const hb_tag_t tableTag = HB_OT_TAG_hhea; +}; +struct vhea : _hea { + static const hb_tag_t tableTag = HB_OT_TAG_vhea; +}; + } /* namespace OT */ diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index e918e3b..642c636 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -35,22 +35,25 @@ namespace OT { /* * hmtx -- The Horizontal Metrics Table + * vmtx -- The Vertical Metrics Table */ #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x') +#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x') -struct LongHorMetric +struct LongMetric { - USHORT advanceWidth; - SHORT lsb; + USHORT advance; /* Advance width/height. */ + SHORT lsb; /* Leading (left/top) side bearing. */ public: DEFINE_SIZE_STATIC (4); }; -struct hmtx +struct _mtx { - static const hb_tag_t tableTag = HB_OT_TAG_hmtx; + static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx; + static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx; inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); @@ -60,7 +63,7 @@ struct hmtx } public: - LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side + LongMetric longHorMetric[VAR]; /* Paired advance width and leading * bearing values for each glyph. The * value numOfHMetrics comes from * the 'hhea' table. If the font is @@ -68,23 +71,29 @@ struct hmtx * be in the array, but that entry is * required. The last entry applies to * all subsequent glyphs. */ - SHORT leftSideBearingX[VAR]; /* Here the advanceWidth is assumed - * to be the same as the advanceWidth + SHORT leadingBearingX[VAR]; /* Here the advance is assumed + * to be the same as the advance * for the last entry above. The * number of entries in this array is * derived from numGlyphs (from 'maxp' - * table) minus numberOfHMetrics. This - * generally is used with a run of - * monospaced glyphs (e.g., Kanji + * table) minus numberOfLongMetrics. + * This generally is used with a run + * of monospaced glyphs (e.g., Kanji * fonts or Courier fonts). Only one * run is allowed and it must be at * the end. This allows a monospaced - * font to vary the left side bearing + * font to vary the side bearing * values for each glyph. */ public: - DEFINE_SIZE_ARRAY2 (0, longHorMetric, leftSideBearingX); + DEFINE_SIZE_ARRAY2 (0, longHorMetric, leadingBearingX); }; +struct hmtx : _mtx { + static const hb_tag_t tableTag = HB_OT_TAG_hmtx; +}; +struct vmtx : _mtx { + static const hb_tag_t tableTag = HB_OT_TAG_vmtx; +}; } /* namespace OT */ _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/harfbuzz