1 /* 2 * Copyright 2011,2014 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, Roozbeh Pournader 25 */ 26 27 #include "hb-private.hh" 28 29 #include "hb-ot.h" 30 31 #include "hb-font-private.hh" 32 33 #include "hb-ot-cmap-table.hh" 34 #include "hb-ot-hhea-table.hh" 35 #include "hb-ot-hmtx-table.hh" 36 37 38 39 struct hb_ot_font_t 40 { 41 unsigned int num_glyphs; 42 unsigned int num_hmetrics; 43 const OT::hmtx *hmtx; 44 hb_blob_t *hmtx_blob; 45 46 const OT::CmapSubtable *cmap; 47 const OT::CmapSubtable *cmap_uvs; 48 hb_blob_t *cmap_blob; 49 }; 50 51 52 static hb_ot_font_t * 53 _hb_ot_font_create (hb_font_t *font) 54 { 55 hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); 56 57 if (unlikely (!ot_font)) 58 return NULL; 59 60 ot_font->num_glyphs = font->face->get_num_glyphs (); 61 62 { 63 hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea)); 64 const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob); 65 ot_font->num_hmetrics = hhea->numberOfHMetrics; 66 hb_blob_destroy (hhea_blob); 67 } 68 ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx)); 69 if (unlikely (!ot_font->num_hmetrics || 70 2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob))) 71 { 72 hb_blob_destroy (ot_font->hmtx_blob); 73 free (ot_font); 74 return NULL; 75 } 76 ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob); 77 78 ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap)); 79 const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (ot_font->cmap_blob); 80 const OT::CmapSubtable *subtable = NULL; 81 const OT::CmapSubtable *subtable_uvs = NULL; 82 83 /* 32-bit subtables. */ 84 if (!subtable) subtable = cmap->find_subtable (3, 10); 85 if (!subtable) subtable = cmap->find_subtable (0, 6); 86 if (!subtable) subtable = cmap->find_subtable (0, 4); 87 /* 16-bit subtables. */ 88 if (!subtable) subtable = cmap->find_subtable (3, 1); 89 if (!subtable) subtable = cmap->find_subtable (0, 3); 90 if (!subtable) subtable = cmap->find_subtable (0, 2); 91 if (!subtable) subtable = cmap->find_subtable (0, 1); 92 if (!subtable) subtable = cmap->find_subtable (0, 0); 93 /* Meh. */ 94 if (!subtable) subtable = &OT::Null(OT::CmapSubtable); 95 96 /* UVS subtable. */ 97 if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5); 98 /* Meh. */ 99 if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable); 100 101 ot_font->cmap = subtable; 102 ot_font->cmap_uvs = subtable_uvs; 103 104 return ot_font; 105 } 106 107 static void 108 _hb_ot_font_destroy (hb_ot_font_t *ot_font) 109 { 110 hb_blob_destroy (ot_font->cmap_blob); 111 hb_blob_destroy (ot_font->hmtx_blob); 112 113 free (ot_font); 114 } 115 116 117 static hb_bool_t 118 hb_ot_get_glyph (hb_font_t *font HB_UNUSED, 119 void *font_data, 120 hb_codepoint_t unicode, 121 hb_codepoint_t variation_selector, 122 hb_codepoint_t *glyph, 123 void *user_data HB_UNUSED) 124 125 { 126 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 127 128 if (unlikely (variation_selector)) 129 { 130 switch (ot_font->cmap_uvs->get_glyph_variant (unicode, 131 variation_selector, 132 glyph)) 133 { 134 case OT::GLYPH_VARIANT_NOT_FOUND: return false; 135 case OT::GLYPH_VARIANT_FOUND: return true; 136 case OT::GLYPH_VARIANT_USE_DEFAULT: break; 137 } 138 } 139 140 return ot_font->cmap->get_glyph (unicode, glyph); 141 } 142 143 static hb_position_t 144 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, 145 void *font_data, 146 hb_codepoint_t glyph, 147 void *user_data HB_UNUSED) 148 { 149 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 150 151 if (unlikely (glyph >= ot_font->num_glyphs)) 152 return 0; /* Maybe better to return notdef's advance instead? */ 153 154 if (glyph >= ot_font->num_hmetrics) 155 glyph = ot_font->num_hmetrics - 1; 156 157 return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth); 158 } 159 160 static hb_position_t 161 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, 162 void *font_data, 163 hb_codepoint_t glyph, 164 void *user_data HB_UNUSED) 165 { 166 /* TODO */ 167 return 0; 168 } 169 170 static hb_bool_t 171 hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED, 172 void *font_data HB_UNUSED, 173 hb_codepoint_t glyph HB_UNUSED, 174 hb_position_t *x HB_UNUSED, 175 hb_position_t *y HB_UNUSED, 176 void *user_data HB_UNUSED) 177 { 178 /* We always work in the horizontal coordinates. */ 179 return true; 180 } 181 182 static hb_bool_t 183 hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED, 184 void *font_data, 185 hb_codepoint_t glyph, 186 hb_position_t *x, 187 hb_position_t *y, 188 void *user_data HB_UNUSED) 189 { 190 /* TODO */ 191 return false; 192 } 193 194 static hb_position_t 195 hb_ot_get_glyph_h_kerning (hb_font_t *font, 196 void *font_data, 197 hb_codepoint_t left_glyph, 198 hb_codepoint_t right_glyph, 199 void *user_data HB_UNUSED) 200 { 201 /* TODO */ 202 return 0; 203 } 204 205 static hb_position_t 206 hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, 207 void *font_data HB_UNUSED, 208 hb_codepoint_t top_glyph HB_UNUSED, 209 hb_codepoint_t bottom_glyph HB_UNUSED, 210 void *user_data HB_UNUSED) 211 { 212 return 0; 213 } 214 215 static hb_bool_t 216 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, 217 void *font_data, 218 hb_codepoint_t glyph, 219 hb_glyph_extents_t *extents, 220 void *user_data HB_UNUSED) 221 { 222 /* TODO */ 223 return false; 224 } 225 226 static hb_bool_t 227 hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED, 228 void *font_data, 229 hb_codepoint_t glyph, 230 unsigned int point_index, 231 hb_position_t *x, 232 hb_position_t *y, 233 void *user_data HB_UNUSED) 234 { 235 /* TODO */ 236 return false; 237 } 238 239 static hb_bool_t 240 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, 241 void *font_data, 242 hb_codepoint_t glyph, 243 char *name, unsigned int size, 244 void *user_data HB_UNUSED) 245 { 246 /* TODO */ 247 return false; 248 } 249 250 static hb_bool_t 251 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, 252 void *font_data, 253 const char *name, int len, /* -1 means nul-terminated */ 254 hb_codepoint_t *glyph, 255 void *user_data HB_UNUSED) 256 { 257 /* TODO */ 258 return false; 259 } 260 261 262 static hb_font_funcs_t * 263 _hb_ot_get_font_funcs (void) 264 { 265 static const hb_font_funcs_t ot_ffuncs = { 266 HB_OBJECT_HEADER_STATIC, 267 268 true, /* immutable */ 269 270 { 271 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name, 272 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 273 #undef HB_FONT_FUNC_IMPLEMENT 274 } 275 }; 276 277 return const_cast<hb_font_funcs_t *> (&ot_ffuncs); 278 } 279 280 281 void 282 hb_ot_font_set_funcs (hb_font_t *font) 283 { 284 hb_ot_font_t *ot_font = _hb_ot_font_create (font); 285 if (unlikely (!ot_font)) 286 return; 287 288 hb_font_set_funcs (font, 289 _hb_ot_get_font_funcs (), 290 ot_font, 291 (hb_destroy_func_t) _hb_ot_font_destroy); 292 } 293