1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 /*
  31  * Copyright © 2011,2014  Google, Inc.
  32  *
  33  *  This is part of HarfBuzz, a text shaping library.
  34  *
  35  * Permission is hereby granted, without written agreement and without
  36  * license or royalty fees, to use, copy, modify, and distribute this
  37  * software and its documentation for any purpose, provided that the
  38  * above copyright notice and the following two paragraphs appear in
  39  * all copies of this software.
  40  *
  41  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  42  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  43  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  44  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  45  * DAMAGE.
  46  *
  47  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  48  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  49  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  50  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  51  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  52  *
  53  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
  54  */
  55 
  56 #include "hb-private.hh"
  57 
  58 #include "hb-ot.h"
  59 
  60 #include "hb-font-private.hh"
  61 
  62 #include "hb-ot-cmap-table.hh"
  63 #include "hb-ot-glyf-table.hh"
  64 #include "hb-ot-head-table.hh"
  65 #include "hb-ot-hhea-table.hh"
  66 #include "hb-ot-hmtx-table.hh"
  67 
  68 
  69 struct hb_ot_face_metrics_accelerator_t
  70 {
  71   unsigned int num_metrics;
  72   unsigned int num_advances;
  73   unsigned int default_advance;
  74   const OT::_mtx *table;
  75   hb_blob_t *blob;
  76 
  77   inline void init (hb_face_t *face,
  78                     hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
  79                     unsigned int default_advance_)
  80   {
  81     this->default_advance = default_advance_;
  82     this->num_metrics = face->get_num_glyphs ();
  83 
  84     hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
  85     const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
  86     this->num_advances = _hea->numberOfLongMetrics;
  87     hb_blob_destroy (_hea_blob);
  88 
  89     this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
  90     if (unlikely (!this->num_advances ||
  91                   2 * (this->num_advances + this->num_metrics) > hb_blob_get_length (this->blob)))
  92     {
  93       this->num_metrics = this->num_advances = 0;
  94       hb_blob_destroy (this->blob);
  95       this->blob = hb_blob_get_empty ();
  96     }
  97     this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
  98   }
  99 
 100   inline void fini (void)
 101   {
 102     hb_blob_destroy (this->blob);
 103   }
 104 
 105   inline unsigned int get_advance (hb_codepoint_t glyph) const
 106   {
 107     if (unlikely (glyph >= this->num_metrics))
 108     {
 109       /* If this->num_metrics is zero, it means we don't have the metrics table
 110        * for this direction: return default advance.  Otherwise, it means that the
 111        * glyph index is out of bound: return zero. */
 112       if (this->num_metrics)
 113         return 0;
 114       else
 115         return this->default_advance;
 116     }
 117 
 118     if (glyph >= this->num_advances)
 119       glyph = this->num_advances - 1;
 120 
 121     return this->table->longMetric[glyph].advance;
 122   }
 123 };
 124 
 125 struct hb_ot_face_glyf_accelerator_t
 126 {
 127   bool short_offset;
 128   unsigned int num_glyphs;
 129   const OT::loca *loca;
 130   const OT::glyf *glyf;
 131   hb_blob_t *loca_blob;
 132   hb_blob_t *glyf_blob;
 133   unsigned int glyf_len;
 134 
 135   inline void init (hb_face_t *face)
 136   {
 137     hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head));
 138     const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob);
 139     if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0)
 140     {
 141       /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
 142       hb_blob_destroy (head_blob);
 143       return;
 144     }
 145     this->short_offset = 0 == head->indexToLocFormat;
 146     hb_blob_destroy (head_blob);
 147 
 148     this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca));
 149     this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob);
 150     this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf));
 151     this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob);
 152 
 153     this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1;
 154     this->glyf_len = hb_blob_get_length (this->glyf_blob);
 155   }
 156 
 157   inline void fini (void)
 158   {
 159     hb_blob_destroy (this->loca_blob);
 160     hb_blob_destroy (this->glyf_blob);
 161   }
 162 
 163   inline bool get_extents (hb_codepoint_t glyph,
 164                            hb_glyph_extents_t *extents) const
 165   {
 166     if (unlikely (glyph >= this->num_glyphs))
 167       return false;
 168 
 169     unsigned int start_offset, end_offset;
 170     if (this->short_offset)
 171     {
 172       start_offset = 2 * this->loca->u.shortsZ[glyph];
 173       end_offset   = 2 * this->loca->u.shortsZ[glyph + 1];
 174     }
 175     else
 176     {
 177       start_offset = this->loca->u.longsZ[glyph];
 178       end_offset   = this->loca->u.longsZ[glyph + 1];
 179     }
 180 
 181     if (start_offset > end_offset || end_offset > this->glyf_len)
 182       return false;
 183 
 184     if (end_offset - start_offset < OT::glyfGlyphHeader::static_size)
 185       return true; /* Empty glyph; zero extents. */
 186 
 187     const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset);
 188 
 189     extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
 190     extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
 191     extents->width     = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
 192     extents->height    = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
 193 
 194     return true;
 195   }
 196 };
 197 
 198 struct hb_ot_face_cmap_accelerator_t
 199 {
 200   const OT::CmapSubtable *table;
 201   const OT::CmapSubtable *uvs_table;
 202   hb_blob_t *blob;
 203 
 204   inline void init (hb_face_t *face)
 205   {
 206     this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
 207     const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
 208     const OT::CmapSubtable *subtable = NULL;
 209     const OT::CmapSubtable *subtable_uvs = NULL;
 210 
 211     /* 32-bit subtables. */
 212     if (!subtable) subtable = cmap->find_subtable (3, 10);
 213     if (!subtable) subtable = cmap->find_subtable (0, 6);
 214     if (!subtable) subtable = cmap->find_subtable (0, 4);
 215     /* 16-bit subtables. */
 216     if (!subtable) subtable = cmap->find_subtable (3, 1);
 217     if (!subtable) subtable = cmap->find_subtable (0, 3);
 218     if (!subtable) subtable = cmap->find_subtable (0, 2);
 219     if (!subtable) subtable = cmap->find_subtable (0, 1);
 220     if (!subtable) subtable = cmap->find_subtable (0, 0);
 221     if (!subtable) subtable = cmap->find_subtable (3, 0);
 222     /* Meh. */
 223     if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
 224 
 225     /* UVS subtable. */
 226     if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
 227     /* Meh. */
 228     if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
 229 
 230     this->table = subtable;
 231     this->uvs_table = subtable_uvs;
 232   }
 233 
 234   inline void fini (void)
 235   {
 236     hb_blob_destroy (this->blob);
 237   }
 238 
 239   inline bool get_glyph (hb_codepoint_t  unicode,
 240                          hb_codepoint_t  variation_selector,
 241                          hb_codepoint_t *glyph) const
 242   {
 243     if (unlikely (variation_selector))
 244     {
 245       switch (this->uvs_table->get_glyph_variant (unicode,
 246                                                   variation_selector,
 247                                                   glyph))
 248       {
 249         case OT::GLYPH_VARIANT_NOT_FOUND:       return false;
 250         case OT::GLYPH_VARIANT_FOUND:           return true;
 251         case OT::GLYPH_VARIANT_USE_DEFAULT:     break;
 252       }
 253     }
 254 
 255     return this->table->get_glyph (unicode, glyph);
 256   }
 257 };
 258 
 259 
 260 struct hb_ot_font_t
 261 {
 262   hb_ot_face_cmap_accelerator_t cmap;
 263   hb_ot_face_metrics_accelerator_t h_metrics;
 264   hb_ot_face_metrics_accelerator_t v_metrics;
 265   hb_ot_face_glyf_accelerator_t glyf;
 266 };
 267 
 268 
 269 static hb_ot_font_t *
 270 _hb_ot_font_create (hb_face_t *face)
 271 {
 272   hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
 273 
 274   if (unlikely (!ot_font))
 275     return NULL;
 276 
 277   unsigned int upem = face->get_upem ();
 278 
 279   ot_font->cmap.init (face);
 280   ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
 281   ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */
 282   ot_font->glyf.init (face);
 283 
 284   return ot_font;
 285 }
 286 
 287 static void
 288 _hb_ot_font_destroy (hb_ot_font_t *ot_font)
 289 {
 290   ot_font->cmap.fini ();
 291   ot_font->h_metrics.fini ();
 292   ot_font->v_metrics.fini ();
 293   ot_font->glyf.fini ();
 294 
 295   free (ot_font);
 296 }
 297 
 298 
 299 static hb_bool_t
 300 hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
 301                  void *font_data,
 302                  hb_codepoint_t unicode,
 303                  hb_codepoint_t variation_selector,
 304                  hb_codepoint_t *glyph,
 305                  void *user_data HB_UNUSED)
 306 
 307 {
 308   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 309   return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
 310 }
 311 
 312 static hb_position_t
 313 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
 314                            void *font_data,
 315                            hb_codepoint_t glyph,
 316                            void *user_data HB_UNUSED)
 317 {
 318   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 319   return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
 320 }
 321 
 322 static hb_position_t
 323 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
 324                            void *font_data,
 325                            hb_codepoint_t glyph,
 326                            void *user_data HB_UNUSED)
 327 {
 328   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 329   return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph));
 330 }
 331 
 332 static hb_bool_t
 333 hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
 334                           void *font_data HB_UNUSED,
 335                           hb_codepoint_t glyph HB_UNUSED,
 336                           hb_position_t *x HB_UNUSED,
 337                           hb_position_t *y HB_UNUSED,
 338                           void *user_data HB_UNUSED)
 339 {
 340   /* We always work in the horizontal coordinates. */
 341   return true;
 342 }
 343 
 344 static hb_bool_t
 345 hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
 346                           void *font_data,
 347                           hb_codepoint_t glyph,
 348                           hb_position_t *x,
 349                           hb_position_t *y,
 350                           void *user_data HB_UNUSED)
 351 {
 352   /* TODO */
 353   return false;
 354 }
 355 
 356 static hb_position_t
 357 hb_ot_get_glyph_h_kerning (hb_font_t *font,
 358                            void *font_data,
 359                            hb_codepoint_t left_glyph,
 360                            hb_codepoint_t right_glyph,
 361                            void *user_data HB_UNUSED)
 362 {
 363   /* TODO */
 364   return 0;
 365 }
 366 
 367 static hb_position_t
 368 hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
 369                            void *font_data HB_UNUSED,
 370                            hb_codepoint_t top_glyph HB_UNUSED,
 371                            hb_codepoint_t bottom_glyph HB_UNUSED,
 372                            void *user_data HB_UNUSED)
 373 {
 374   /* OpenType doesn't have vertical-kerning other than GPOS. */
 375   return 0;
 376 }
 377 
 378 static hb_bool_t
 379 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
 380                          void *font_data,
 381                          hb_codepoint_t glyph,
 382                          hb_glyph_extents_t *extents,
 383                          void *user_data HB_UNUSED)
 384 {
 385   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
 386   bool ret = ot_font->glyf.get_extents (glyph, extents);
 387   extents->x_bearing = font->em_scale_x (extents->x_bearing);
 388   extents->y_bearing = font->em_scale_y (extents->y_bearing);
 389   extents->width     = font->em_scale_x (extents->width);
 390   extents->height    = font->em_scale_y (extents->height);
 391   return ret;
 392 }
 393 
 394 static hb_bool_t
 395 hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
 396                                void *font_data,
 397                                hb_codepoint_t glyph,
 398                                unsigned int point_index,
 399                                hb_position_t *x,
 400                                hb_position_t *y,
 401                                void *user_data HB_UNUSED)
 402 {
 403   /* TODO */
 404   return false;
 405 }
 406 
 407 static hb_bool_t
 408 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
 409                       void *font_data,
 410                       hb_codepoint_t glyph,
 411                       char *name, unsigned int size,
 412                       void *user_data HB_UNUSED)
 413 {
 414   /* TODO */
 415   return false;
 416 }
 417 
 418 static hb_bool_t
 419 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
 420                            void *font_data,
 421                            const char *name, int len, /* -1 means nul-terminated */
 422                            hb_codepoint_t *glyph,
 423                            void *user_data HB_UNUSED)
 424 {
 425   /* TODO */
 426   return false;
 427 }
 428 
 429 
 430 static hb_font_funcs_t *
 431 _hb_ot_get_font_funcs (void)
 432 {
 433   static const hb_font_funcs_t ot_ffuncs = {
 434     HB_OBJECT_HEADER_STATIC,
 435 
 436     true, /* immutable */
 437 
 438     {
 439 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
 440       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 441 #undef HB_FONT_FUNC_IMPLEMENT
 442     }
 443   };
 444 
 445   return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
 446 }
 447 
 448 
 449 /**
 450  * Since: 0.9.28
 451  **/
 452 void
 453 hb_ot_font_set_funcs (hb_font_t *font)
 454 {
 455   hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
 456   if (unlikely (!ot_font))
 457     return;
 458 
 459   hb_font_set_funcs (font,
 460                      _hb_ot_get_font_funcs (),
 461                      ot_font,
 462                      (hb_destroy_func_t) _hb_ot_font_destroy);
 463 }