| /* |
| * 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" |
| #include "hb-ot-head-table.hh" |
| |
| |
| namespace OT { |
| |
| |
| /* |
| * loca -- Index to Location |
| */ |
| |
| #define HB_OT_TAG_loca HB_TAG('l','o','c','a') |
| |
| |
| struct loca |
| { |
| friend struct glyf; |
| |
| static const hb_tag_t tableTag = HB_OT_TAG_loca; |
| |
| inline bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (true); |
| } |
| |
| protected: |
| UINT8 dataX[VAR]; /* Location data. */ |
| DEFINE_SIZE_ARRAY (0, dataX); |
| }; |
| |
| |
| /* |
| * 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 (true); |
| } |
| |
| struct GlyphHeader |
| { |
| INT16 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. */ |
| FWORD xMin; /* Minimum x for coordinate data. */ |
| FWORD yMin; /* Minimum y for coordinate data. */ |
| FWORD xMax; /* Maximum x for coordinate data. */ |
| FWORD yMax; /* Maximum y for coordinate data. */ |
| |
| DEFINE_SIZE_STATIC (10); |
| }; |
| |
| struct accelerator_t |
| { |
| inline void init (hb_face_t *face) |
| { |
| hb_blob_t *head_blob = Sanitizer<head>::sanitize (face->reference_table (HB_OT_TAG_head)); |
| const head *head_table = Sanitizer<head>::lock_instance (head_blob); |
| if ((unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0) |
| { |
| /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ |
| hb_blob_destroy (head_blob); |
| return; |
| } |
| short_offset = 0 == head_table->indexToLocFormat; |
| hb_blob_destroy (head_blob); |
| |
| loca_blob = Sanitizer<loca>::sanitize (face->reference_table (HB_OT_TAG_loca)); |
| loca_table = Sanitizer<loca>::lock_instance (loca_blob); |
| glyf_blob = Sanitizer<glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf)); |
| glyf_table = Sanitizer<glyf>::lock_instance (glyf_blob); |
| |
| num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1; |
| glyf_len = hb_blob_get_length (glyf_blob); |
| } |
| |
| inline void fini (void) |
| { |
| hb_blob_destroy (loca_blob); |
| hb_blob_destroy (glyf_blob); |
| } |
| |
| inline bool get_extents (hb_codepoint_t glyph, |
| hb_glyph_extents_t *extents) const |
| { |
| if (unlikely (glyph >= num_glyphs)) |
| return false; |
| |
| unsigned int start_offset, end_offset; |
| if (short_offset) |
| { |
| const UINT16 *offsets = (const UINT16 *) loca_table->dataX; |
| start_offset = 2 * offsets[glyph]; |
| end_offset = 2 * offsets[glyph + 1]; |
| } |
| else |
| { |
| const UINT32 *offsets = (const UINT32 *) loca_table->dataX; |
| start_offset = offsets[glyph]; |
| end_offset = offsets[glyph + 1]; |
| } |
| |
| if (start_offset > end_offset || end_offset > glyf_len) |
| return false; |
| |
| if (end_offset - start_offset < GlyphHeader::static_size) |
| return true; /* Empty glyph; zero extents. */ |
| |
| const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, 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; |
| } |
| |
| private: |
| bool short_offset; |
| unsigned int num_glyphs; |
| const loca *loca_table; |
| const glyf *glyf_table; |
| hb_blob_t *loca_blob; |
| hb_blob_t *glyf_blob; |
| unsigned int glyf_len; |
| }; |
| |
| protected: |
| UINT8 dataX[VAR]; /* Glyphs data. */ |
| |
| DEFINE_SIZE_ARRAY (0, dataX); |
| }; |
| |
| } /* namespace OT */ |
| |
| |
| #endif /* HB_OT_GLYF_TABLE_HH */ |