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 39struct 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 52static 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 (0, 6); 85 if (!subtable) subtable = cmap->find_subtable (0, 4); 86 if (!subtable) subtable = cmap->find_subtable (3, 10); 87 /* 16-bit subtables. */ 88 if (!subtable) subtable = cmap->find_subtable (0, 3); 89 if (!subtable) subtable = cmap->find_subtable (3, 1); 90 /* Meh. */ 91 if (!subtable) subtable = &OT::Null(OT::CmapSubtable); 92 93 /* UVS subtable. */ 94 if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5); 95 /* Meh. */ 96 if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable); 97 98 ot_font->cmap = subtable; 99 ot_font->cmap_uvs = subtable_uvs; 100 101 return ot_font; 102} 103 104static void 105_hb_ot_font_destroy (hb_ot_font_t *ot_font) 106{ 107 hb_blob_destroy (ot_font->cmap_blob); 108 hb_blob_destroy (ot_font->hmtx_blob); 109 110 free (ot_font); 111} 112 113 114static hb_bool_t 115hb_ot_get_glyph (hb_font_t *font HB_UNUSED, 116 void *font_data, 117 hb_codepoint_t unicode, 118 hb_codepoint_t variation_selector, 119 hb_codepoint_t *glyph, 120 void *user_data HB_UNUSED) 121 122{ 123 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 124 125 if (unlikely (variation_selector)) 126 { 127 switch (ot_font->cmap_uvs->get_glyph_variant (unicode, 128 variation_selector, 129 glyph)) 130 { 131 case OT::GLYPH_VARIANT_NOT_FOUND: return false; 132 case OT::GLYPH_VARIANT_FOUND: return true; 133 case OT::GLYPH_VARIANT_USE_DEFAULT: break; 134 } 135 } 136 137 return ot_font->cmap->get_glyph (unicode, glyph); 138} 139 140static hb_position_t 141hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, 142 void *font_data, 143 hb_codepoint_t glyph, 144 void *user_data HB_UNUSED) 145{ 146 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 147 148 if (unlikely (glyph >= ot_font->num_glyphs)) 149 return 0; /* Maybe better to return notdef's advance instead? */ 150 151 if (glyph >= ot_font->num_hmetrics) 152 glyph = ot_font->num_hmetrics - 1; 153 154 return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth); 155} 156 157static hb_position_t 158hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, 159 void *font_data, 160 hb_codepoint_t glyph, 161 void *user_data HB_UNUSED) 162{ 163 /* TODO */ 164 return 0; 165} 166 167static hb_bool_t 168hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED, 169 void *font_data HB_UNUSED, 170 hb_codepoint_t glyph HB_UNUSED, 171 hb_position_t *x HB_UNUSED, 172 hb_position_t *y HB_UNUSED, 173 void *user_data HB_UNUSED) 174{ 175 /* We always work in the horizontal coordinates. */ 176 return true; 177} 178 179static hb_bool_t 180hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED, 181 void *font_data, 182 hb_codepoint_t glyph, 183 hb_position_t *x, 184 hb_position_t *y, 185 void *user_data HB_UNUSED) 186{ 187 /* TODO */ 188 return false; 189} 190 191static hb_position_t 192hb_ot_get_glyph_h_kerning (hb_font_t *font, 193 void *font_data, 194 hb_codepoint_t left_glyph, 195 hb_codepoint_t right_glyph, 196 void *user_data HB_UNUSED) 197{ 198 /* TODO */ 199 return 0; 200} 201 202static hb_position_t 203hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, 204 void *font_data HB_UNUSED, 205 hb_codepoint_t top_glyph HB_UNUSED, 206 hb_codepoint_t bottom_glyph HB_UNUSED, 207 void *user_data HB_UNUSED) 208{ 209 return 0; 210} 211 212static hb_bool_t 213hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, 214 void *font_data, 215 hb_codepoint_t glyph, 216 hb_glyph_extents_t *extents, 217 void *user_data HB_UNUSED) 218{ 219 /* TODO */ 220 return false; 221} 222 223static hb_bool_t 224hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED, 225 void *font_data, 226 hb_codepoint_t glyph, 227 unsigned int point_index, 228 hb_position_t *x, 229 hb_position_t *y, 230 void *user_data HB_UNUSED) 231{ 232 /* TODO */ 233 return false; 234} 235 236static hb_bool_t 237hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, 238 void *font_data, 239 hb_codepoint_t glyph, 240 char *name, unsigned int size, 241 void *user_data HB_UNUSED) 242{ 243 /* TODO */ 244 return false; 245} 246 247static hb_bool_t 248hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, 249 void *font_data, 250 const char *name, int len, /* -1 means nul-terminated */ 251 hb_codepoint_t *glyph, 252 void *user_data HB_UNUSED) 253{ 254 /* TODO */ 255 return false; 256} 257 258 259static hb_font_funcs_t * 260_hb_ot_get_font_funcs (void) 261{ 262 static const hb_font_funcs_t ot_ffuncs = { 263 HB_OBJECT_HEADER_STATIC, 264 265 true, /* immutable */ 266 267 { 268#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name, 269 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 270#undef HB_FONT_FUNC_IMPLEMENT 271 } 272 }; 273 274 return const_cast<hb_font_funcs_t *> (&ot_ffuncs); 275} 276 277 278void 279hb_ot_font_set_funcs (hb_font_t *font) 280{ 281 hb_ot_font_t *ot_font = _hb_ot_font_create (font); 282 if (unlikely (!ot_font)) 283 return; 284 285 hb_font_set_funcs (font, 286 _hb_ot_get_font_funcs (), 287 ot_font, 288 (hb_destroy_func_t) _hb_ot_font_destroy); 289} 290