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-glyf-table.hh"
  35 #include "hb-ot-head-table.hh"
  36 #include "hb-ot-hhea-table.hh"
  37 #include "hb-ot-hmtx-table.hh"
  38 
  39 
  40 struct hb_ot_face_metrics_accelerator_t
  41 {
  42   unsigned int num_metrics;
  43   unsigned int num_advances;
  44   unsigned int default_advance;
  45   const OT::_mtx *table;
  46   hb_blob_t *blob;
  47 
  48   inline void init (hb_face_t *face,
  49                     hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
  50                     unsigned int default_advance_)
  51   {
  52     this->default_advance = default_advance_;
  53     this->num_metrics = face->get_num_glyphs ();
  54 
  55     hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
  56     const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
  57     this->num_advances = _hea->numberOfLongMetrics;
  58     hb_blob_destroy (_hea_blob);
  59 
  60     this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
  61     if (unlikely (!this->num_advances ||
  62                   2 * (this->num_advances + this->num_metrics) > hb_blob_get_length (this->blob)))
  63     {
  64       this->num_metrics = this->num_advances = 0;
  65       hb_blob_destroy (this->blob);
  66       this->blob = hb_blob_get_empty ();
  67     }
  68     this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
  69   }
  70 
  71   inline void fini (void)
  72   {
  73     hb_blob_destroy (this->blob);
  74   }
  75 
  76   inline unsigned int get_advance (hb_codepoint_t glyph) const
  77   {
  78     if (unlikely (glyph >= this->num_metrics))
  79     {
  80       /* If this->num_metrics is zero, it means we don't have the metrics table
  81        * for this direction: return default advance.  Otherwise, it means that the
  82        * glyph index is out of bound: return zero. */
  83       if (this->num_metrics)
  84         return 0;
  85       else
  86         return this->default_advance;
  87     }
  88 
  89     if (glyph >= this->num_advances)
  90       glyph = this->num_advances - 1;
  91 
  92     return this->table->longMetric[glyph].advance;
  93   }
  94 };
  95 
  96 struct hb_ot_face_glyf_accelerator_t
  97 {
  98   bool short_offset;
  99   unsigned int num_glyphs;
 100   const OT::loca *loca;
 101   const OT::glyf *glyf;
 102   hb_blob_t *loca_blob;
 103   hb_blob_t *glyf_blob;
 104   unsigned int glyf_len;
 105 
 106   inline void init (hb_face_t *face)
 107   {
 108     hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head));
 109     const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob);
 110     if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0)
 111     {
 112       /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
 113       hb_blob_destroy (head_blob);
 114       return;
 115     }
 116     this->short_offset = 0 == head->indexToLocFormat;
 117     hb_blob_destroy (head_blob);
 118 
 119     this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca));
 120     this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob);
 121     this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf));
 122     this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob);
 123 
 124     this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1;
 125     this->glyf_len = hb_blob_get_length (this->glyf_blob);
 126   }
 127 
 128   inline void fini (void)
 129   {
 130     hb_blob_destroy (this->loca_blob);
 131     hb_blob_destroy (this->glyf_blob);
 132   }
 133 
 134   inline bool get_extents (hb_codepoint_t glyph,
 135                            hb_glyph_extents_t *extents) const
 136   {
 137     if (unlikely (glyph >= this->num_glyphs))
 138       return false;
 139 
 140     unsigned int start_offset, end_offset;
 141     if (this->short_offset)
 142     {
 143       start_offset = 2 * this->loca->u.shortsZ[glyph];
 144       end_offset   = 2 * this->loca->u.shortsZ[glyph + 1];
 145     }
 146     else
 147     {
 148       start_offset = this->loca->u.longsZ[glyph];
 149       end_offset   = this->loca->u.longsZ[glyph + 1];
 150     }
 151 
 152     if (start_offset > end_offset || end_offset > this->glyf_len)
 153       return false;
 154 
 155     if (end_offset - start_offset < OT::glyfGlyphHeader::static_size)
 156       return true; /* Empty glyph; zero extents. */
 157 
 158     const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset);
 159 
 160     extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
 161     extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
 162     extents->width     = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
 163     extents->height    = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
 164 
 165     return true;
 166   }
 167 };
 168 
 169 struct hb_ot_face_cmap_accelerator_t
 170 {
 171   const OT::CmapSubtable *table;
 172   const OT::CmapSubtable *uvs_table;
 173   hb_blob_t *blob;
 174 
 175   inline void init (hb_face_t *face)
 176   {
 177     this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
 178     const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
 179     const OT::CmapSubtable *subtable = NULL;
 180     const OT::CmapSubtable *subtable_uvs = NULL;
 181 
 182     /* 32-bit subtables. */
 183     if (!subtable) subtable = cmap->find_subtable (3, 10);
 184     if (!subtable) subtable = cmap->find_subtable (0, 6);
 185     if (!subtable) subtable = cmap->find_subtable (0, 4);
 186     /* 16-bit subtables. */
 187     if (!subtable) subtable = cmap->find_subtable (3, 1);
 188     if (!subtable) subtable = cmap->find_subtable (0, 3);
 189     if (!subtable) subtable = cmap->find_subtable (0, 2);
 190     if (!subtable) subtable = cmap->find_subtable (0, 1);
 191     if (!subtable) subtable = cmap->find_subtable (0, 0);
 192     if (!subtable) subtable = cmap->find_subtable (3, 0);
 193     /* Meh. */
 194     if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
 195 
 196     /* UVS subtable. */
 197     if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
 198     /* Meh. */
 199     if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
 200 
 201     this->table = subtable;
 202     this->uvs_table = subtable_uvs;
 203   }
 204 
 205   inline void fini (void)
 206   {
 207     hb_blob_destroy (this->blob);
 208   }
 209 
 210   inline bool get_glyph (hb_codepoint_t  unicode,
 211                          hb_codepoint_t  variation_selector,
 212                          hb_codepoint_t *glyph) const
 213   {
 214     if (unlikely (variation_selector))
 215     {
 216       switch (this->uvs_table->get_glyph_variant (unicode,
 217                                                   variation_selector,
 218                                                   glyph))
 219       {
 220         case OT::GLYPH_VARIANT_NOT_FOUND:       return false;
 221         case OT::GLYPH_VARIANT_FOUND:           return true;
 222         case OT::GLYPH_VARIANT_USE_DEFAULT:     break;
 223       }
 224     }
 225 
 226     return this->table->get_glyph (unicode, glyph);
 227   }
 228 };
 229 
 230 
 231 struct hb_ot_font_t
 232 {
 233   hb_ot_face_cmap_accelerator_t cmap;
 234   hb_ot_face_metrics_accelerator_t h_metrics;
 235   hb_ot_face_metrics_accelerator_t v_metrics;
 236   hb_ot_face_glyf_accelerator_t glyf;
 237 };
 238 
 239 
 240 static hb_ot_font_t *
 241 _hb_ot_font_create (hb_face_t *face)
 242 {
 243   hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
 244 
 245   if (unlikely (!ot_font))
 246     return NULL;
 247 
 248   unsigned int upem = face->get_upem ();
 249 
 250   ot_font->cmap.init (face);
 251   ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
 252   ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */
 253   ot_font->glyf.init (face);
 254 
 255   return ot_font;
 256 }
 257 
 258 static void
 259 _hb_ot_font_destroy (hb_ot_font_t *ot_font)
 260 {
 261   ot_font->cmap.fini ();
 262   ot_font->h_metrics.fini ();
 263   ot_font->v_metrics.fini ();
 264   ot_font->glyf.fini ();
 265 
 266   free (ot_font);
 267 }
 268 
 269 
 270 static hb_bool_t
 271 hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
 272                  void *font_data,
 273                  hb_codepoint_t unicode,
 274                  hb_codepoint_t variation_selector,
 275                  hb_codepoint_t *glyph,
 276                  void *user_data HB_UNUSED)
 277 
 278 {
 279   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 280   return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
 281 }
 282 
 283 static hb_position_t
 284 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
 285                            void *font_data,
 286                            hb_codepoint_t glyph,
 287                            void *user_data HB_UNUSED)
 288 {
 289   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 290   return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
 291 }
 292 
 293 static hb_position_t
 294 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
 295                            void *font_data,
 296                            hb_codepoint_t glyph,
 297                            void *user_data HB_UNUSED)
 298 {
 299   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 300   return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph));
 301 }
 302 
 303 static hb_bool_t
 304 hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
 305                           void *font_data HB_UNUSED,
 306                           hb_codepoint_t glyph HB_UNUSED,
 307                           hb_position_t *x HB_UNUSED,
 308                           hb_position_t *y HB_UNUSED,
 309                           void *user_data HB_UNUSED)
 310 {
 311   /* We always work in the horizontal coordinates. */
 312   return true;
 313 }
 314 
 315 static hb_bool_t
 316 hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
 317                           void *font_data,
 318                           hb_codepoint_t glyph,
 319                           hb_position_t *x,
 320                           hb_position_t *y,
 321                           void *user_data HB_UNUSED)
 322 {
 323   /* TODO */
 324   return false;
 325 }
 326 
 327 static hb_position_t
 328 hb_ot_get_glyph_h_kerning (hb_font_t *font,
 329                            void *font_data,
 330                            hb_codepoint_t left_glyph,
 331                            hb_codepoint_t right_glyph,
 332                            void *user_data HB_UNUSED)
 333 {
 334   /* TODO */
 335   return 0;
 336 }
 337 
 338 static hb_position_t
 339 hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
 340                            void *font_data HB_UNUSED,
 341                            hb_codepoint_t top_glyph HB_UNUSED,
 342                            hb_codepoint_t bottom_glyph HB_UNUSED,
 343                            void *user_data HB_UNUSED)
 344 {
 345   /* OpenType doesn't have vertical-kerning other than GPOS. */
 346   return 0;
 347 }
 348 
 349 static hb_bool_t
 350 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
 351                          void *font_data,
 352                          hb_codepoint_t glyph,
 353                          hb_glyph_extents_t *extents,
 354                          void *user_data HB_UNUSED)
 355 {
 356   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 357   bool ret = ot_font->glyf.get_extents (glyph, extents);
 358   extents->x_bearing = font->em_scale_x (extents->x_bearing);
 359   extents->y_bearing = font->em_scale_y (extents->y_bearing);
 360   extents->width     = font->em_scale_x (extents->width);
 361   extents->height    = font->em_scale_y (extents->height);
 362   return ret;
 363 }
 364 
 365 static hb_bool_t
 366 hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
 367                                void *font_data,
 368                                hb_codepoint_t glyph,
 369                                unsigned int point_index,
 370                                hb_position_t *x,
 371                                hb_position_t *y,
 372                                void *user_data HB_UNUSED)
 373 {
 374   /* TODO */
 375   return false;
 376 }
 377 
 378 static hb_bool_t
 379 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
 380                       void *font_data,
 381                       hb_codepoint_t glyph,
 382                       char *name, unsigned int size,
 383                       void *user_data HB_UNUSED)
 384 {
 385   /* TODO */
 386   return false;
 387 }
 388 
 389 static hb_bool_t
 390 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
 391                            void *font_data,
 392                            const char *name, int len, /* -1 means nul-terminated */
 393                            hb_codepoint_t *glyph,
 394                            void *user_data HB_UNUSED)
 395 {
 396   /* TODO */
 397   return false;
 398 }
 399 
 400 
 401 static hb_font_funcs_t *
 402 _hb_ot_get_font_funcs (void)
 403 {
 404   static const hb_font_funcs_t ot_ffuncs = {
 405     HB_OBJECT_HEADER_STATIC,
 406 
 407     true, /* immutable */
 408 
 409     {
 410 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
 411       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 412 #undef HB_FONT_FUNC_IMPLEMENT
 413     }
 414   };
 415 
 416   return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
 417 }
 418 
 419 
 420 /**
 421  * Since: 0.9.28
 422  **/
 423 void
 424 hb_ot_font_set_funcs (hb_font_t *font)
 425 {
 426   hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
 427   if (unlikely (!ot_font))
 428     return;
 429 
 430   hb_font_set_funcs (font,
 431                      _hb_ot_get_font_funcs (),
 432                      ot_font,
 433                      (hb_destroy_func_t) _hb_ot_font_destroy);
 434 }