summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2015-08-23 14:42:20 +0100
committerBehdad Esfahbod <behdad@behdad.org>2015-08-23 14:42:20 +0100
commitb50fcfa82994f93568a54dd1eb7fd327f6db5586 (patch)
treee13f608415acd68788b086f1fd1b9b164125120e
parent0299b45000b5047c0b9bf0fe51f3b8b68a7982f8 (diff)
downloadharfbuzz-b50fcfa82994f93568a54dd1eb7fd327f6db5586.tar.gz
[ot-font] Implement glyph_extents() for TrueType fonts
This brings ot-fonts into almost-complete shape and mostly in par with ft font.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/hb-font.h9
-rw-r--r--src/hb-ot-font.cc90
-rw-r--r--src/hb-ot-glyf-table.hh104
-rw-r--r--src/hb-ot-head-table.hh3
5 files changed, 198 insertions, 9 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 856aae6a..56997825 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,7 @@ HBSOURCES = \
hb-open-file-private.hh \
hb-open-type-private.hh \
hb-ot-cmap-table.hh \
+ hb-ot-glyf-table.hh \
hb-ot-head-table.hh \
hb-ot-hhea-table.hh \
hb-ot-hmtx-table.hh \
diff --git a/src/hb-font.h b/src/hb-font.h
index cf22589e..5d28b8f4 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -80,12 +80,13 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
/* glyph extents */
+/* Note that height is negative in coordinate systems that grow up. */
typedef struct hb_glyph_extents_t
{
- hb_position_t x_bearing;
- hb_position_t y_bearing;
- hb_position_t width;
- hb_position_t height;
+ hb_position_t x_bearing; /* left side of glyph from origin. */
+ hb_position_t y_bearing; /* top side of glyph from origin. */
+ hb_position_t width; /* distance from left to right side. */
+ hb_position_t height; /* distance from top to bottom side. */
} hb_glyph_extents_t;
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index df6514dd..f5bf6cc4 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -31,6 +31,8 @@
#include "hb-font-private.hh"
#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-head-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-hmtx-table.hh"
@@ -76,8 +78,8 @@ struct hb_ot_face_metrics_accelerator_t
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. */
+ * for this direction: return default advance. Otherwise, it means that the
+ * glyph index is out of bound: return zero. */
if (this->num_metrics)
return 0;
else
@@ -91,6 +93,79 @@ struct hb_ot_face_metrics_accelerator_t
}
};
+struct hb_ot_face_glyf_accelerator_t
+{
+ bool short_offset;
+ unsigned int num_glyphs;
+ const OT::loca *loca;
+ const OT::glyf *glyf;
+ hb_blob_t *loca_blob;
+ hb_blob_t *glyf_blob;
+ unsigned int glyf_len;
+
+ inline void init (hb_face_t *face)
+ {
+ hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head));
+ const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob);
+ if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0)
+ {
+ /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
+ hb_blob_destroy (head_blob);
+ return;
+ }
+ this->short_offset = 0 == head->indexToLocFormat;
+ hb_blob_destroy (head_blob);
+
+ this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca));
+ this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob);
+ this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf));
+ this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob);
+
+ this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1;
+ this->glyf_len = hb_blob_get_length (this->glyf_blob);
+ }
+
+ inline void fini (void)
+ {
+ hb_blob_destroy (this->loca_blob);
+ hb_blob_destroy (this->glyf_blob);
+ }
+
+ inline bool get_extents (hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents) const
+ {
+ if (unlikely (glyph >= this->num_glyphs))
+ return false;
+
+ unsigned int start_offset, end_offset;
+ if (this->short_offset)
+ {
+ start_offset = this->loca->u.shortsZ[glyph];
+ end_offset = this->loca->u.shortsZ[glyph + 1];
+ }
+ else
+ {
+ start_offset = this->loca->u.longsZ[glyph];
+ end_offset = this->loca->u.longsZ[glyph + 1];
+ }
+
+ if (start_offset > end_offset || end_offset > this->glyf_len)
+ return false;
+
+ if (end_offset - start_offset < OT::glyfGlyphHeader::static_size)
+ return true; /* Empty glyph; zero extents. */
+
+ const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset);
+
+ extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
+ extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
+ extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
+ extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
+
+ return true;
+ }
+};
+
struct hb_ot_face_cmap_accelerator_t
{
const OT::CmapSubtable *table;
@@ -158,6 +233,7 @@ 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;
+ hb_ot_face_glyf_accelerator_t glyf;
};
@@ -175,6 +251,7 @@ _hb_ot_font_create (hb_font_t *font)
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? */
+ ot_font->glyf.init (face);
return ot_font;
}
@@ -276,8 +353,13 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
- /* TODO */
- return false;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ bool ret = ot_font->glyf.get_extents (glyph, extents);
+ extents->x_bearing = font->em_scale_x (extents->x_bearing);
+ extents->y_bearing = font->em_scale_y (extents->y_bearing);
+ extents->width = font->em_scale_x (extents->width);
+ extents->height = font->em_scale_y (extents->height);
+ return ret;
}
static hb_bool_t
diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
new file mode 100644
index 00000000..40b54fde
--- /dev/null
+++ b/src/hb-ot-glyf-table.hh
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2015 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_GLYF_TABLE_HH
+#define HB_OT_GLYF_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+namespace OT {
+
+
+/*
+ * loca -- Index to Location
+ */
+
+#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
+
+
+struct loca
+{
+ static const hb_tag_t tableTag = HB_OT_TAG_loca;
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (true);
+ }
+
+ public:
+ union {
+ USHORT shortsZ[VAR]; /* Location offset divided by 2. */
+ ULONG longsZ[VAR]; /* Location offset. */
+ } u;
+ DEFINE_SIZE_ARRAY (0, u.longsZ);
+};
+
+
+/*
+ * glyf -- TrueType Glyph Data
+ */
+
+#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
+
+
+struct glyf
+{
+ static const hb_tag_t tableTag = HB_OT_TAG_glyf;
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ /* We don't check for anything specific here. The users of the
+ * struct do all the hard work... */
+ return TRACE_RETURN (true);
+ }
+
+ public:
+ BYTE dataX[VAR]; /* Glyphs data. */
+
+ DEFINE_SIZE_ARRAY (0, dataX);
+};
+
+struct glyfGlyphHeader
+{
+ SHORT numberOfContours; /* If the number of contours is
+ * greater than or equal to zero,
+ * this is a simple glyph; if negative,
+ * this is a composite glyph. */
+ SHORT xMin; /* Minimum x for coordinate data. */
+ SHORT yMin; /* Minimum y for coordinate data. */
+ SHORT xMax; /* Maximum x for coordinate data. */
+ SHORT yMax; /* Maximum y for coordinate data. */
+
+ DEFINE_SIZE_STATIC (10);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_GLYF_TABLE_HH */
diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh
index 268f1334..157961cf 100644
--- a/src/hb-ot-head-table.hh
+++ b/src/hb-ot-head-table.hh
@@ -138,9 +138,10 @@ struct head
* 2: Like 1 but also contains neutrals;
* -1: Only strongly right to left;
* -2: Like -1 but also contains neutrals. */
+ public:
SHORT indexToLocFormat; /* 0 for short offsets, 1 for long. */
SHORT glyphDataFormat; /* 0 for current format. */
- public:
+
DEFINE_SIZE_STATIC (54);
};