jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc
changeset 34414 e496a8d8fc8a
child 40435 553eb1a50733
equal deleted inserted replaced
34413:bbed9966db6e 34414:e496a8d8fc8a
       
     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 }