1 /* 2 * Copyright 2015 Google, Inc. 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * 24 * Google Author(s): Behdad Esfahbod 25 */ 26 27 #ifndef HB_OT_GLYF_TABLE_HH 28 #define HB_OT_GLYF_TABLE_HH 29 30 #include "hb-open-type-private.hh" 31 #include "hb-ot-head-table.hh" 32 33 34 namespace OT { 35 36 37 /* 38 * loca -- Index to Location 39 */ 40 41 #define HB_OT_TAG_loca HB_TAG('l','o','c','a') 42 43 44 struct loca 45 { 46 friend struct glyf; 47 48 static const hb_tag_t tableTag = HB_OT_TAG_loca; 49 50 inline bool sanitize (hb_sanitize_context_t *c) const 51 { 52 TRACE_SANITIZE (this); 53 return_trace (true); 54 } 55 56 protected: 57 UINT8 dataX[VAR]; /* Location data. */ 58 DEFINE_SIZE_ARRAY (0, dataX); 59 }; 60 61 62 /* 63 * glyf -- TrueType Glyph Data 64 */ 65 66 #define HB_OT_TAG_glyf HB_TAG('g','l','y','f') 67 68 69 struct glyf 70 { 71 static const hb_tag_t tableTag = HB_OT_TAG_glyf; 72 73 inline bool sanitize (hb_sanitize_context_t *c) const 74 { 75 TRACE_SANITIZE (this); 76 /* We don't check for anything specific here. The users of the 77 * struct do all the hard work... */ 78 return_trace (true); 79 } 80 81 struct GlyphHeader 82 { 83 INT16 numberOfContours; /* If the number of contours is 84 * greater than or equal to zero, 85 * this is a simple glyph; if negative, 86 * this is a composite glyph. */ 87 FWORD xMin; /* Minimum x for coordinate data. */ 88 FWORD yMin; /* Minimum y for coordinate data. */ 89 FWORD xMax; /* Maximum x for coordinate data. */ 90 FWORD yMax; /* Maximum y for coordinate data. */ 91 92 DEFINE_SIZE_STATIC (10); 93 }; 94 95 struct accelerator_t 96 { 97 inline void init (hb_face_t *face) 98 { 99 hb_blob_t *head_blob = Sanitizer<head>::sanitize (face->reference_table (HB_OT_TAG_head)); 100 const head *head_table = Sanitizer<head>::lock_instance (head_blob); 101 if ((unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0) 102 { 103 /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ 104 hb_blob_destroy (head_blob); 105 return; 106 } 107 short_offset = 0 == head_table->indexToLocFormat; 108 hb_blob_destroy (head_blob); 109 110 loca_blob = Sanitizer<loca>::sanitize (face->reference_table (HB_OT_TAG_loca)); 111 loca_table = Sanitizer<loca>::lock_instance (loca_blob); 112 glyf_blob = Sanitizer<glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf)); 113 glyf_table = Sanitizer<glyf>::lock_instance (glyf_blob); 114 115 num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1; 116 glyf_len = hb_blob_get_length (glyf_blob); 117 } 118 119 inline void fini (void) 120 { 121 hb_blob_destroy (loca_blob); 122 hb_blob_destroy (glyf_blob); 123 } 124 125 inline bool get_extents (hb_codepoint_t glyph, 126 hb_glyph_extents_t *extents) const 127 { 128 if (unlikely (glyph >= num_glyphs)) 129 return false; 130 131 unsigned int start_offset, end_offset; 132 if (short_offset) 133 { 134 const UINT16 *offsets = (const UINT16 *) loca_table->dataX; 135 start_offset = 2 * offsets[glyph]; 136 end_offset = 2 * offsets[glyph + 1]; 137 } 138 else 139 { 140 const UINT32 *offsets = (const UINT32 *) loca_table->dataX; 141 start_offset = offsets[glyph]; 142 end_offset = offsets[glyph + 1]; 143 } 144 145 if (start_offset > end_offset || end_offset > glyf_len) 146 return false; 147 148 if (end_offset - start_offset < GlyphHeader::static_size) 149 return true; /* Empty glyph; zero extents. */ 150 151 const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset); 152 153 extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); 154 extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax); 155 extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing; 156 extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; 157 158 return true; 159 } 160 161 private: 162 bool short_offset; 163 unsigned int num_glyphs; 164 const loca *loca_table; 165 const glyf *glyf_table; 166 hb_blob_t *loca_blob; 167 hb_blob_t *glyf_blob; 168 unsigned int glyf_len; 169 }; 170 171 protected: 172 UINT8 dataX[VAR]; /* Glyphs data. */ 173 174 DEFINE_SIZE_ARRAY (0, dataX); 175 }; 176 177 } /* namespace OT */ 178 179 180 #endif /* HB_OT_GLYF_TABLE_HH */ 181