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 © 2009  Red Hat, Inc.
  32  * Copyright © 2011  Google, Inc.
  33  *
  34  *  This is part of HarfBuzz, a text shaping library.
  35  *
  36  * Permission is hereby granted, without written agreement and without
  37  * license or royalty fees, to use, copy, modify, and distribute this
  38  * software and its documentation for any purpose, provided that the
  39  * above copyright notice and the following two paragraphs appear in
  40  * all copies of this software.
  41  *
  42  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  43  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  44  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  45  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  46  * DAMAGE.
  47  *
  48  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  49  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  50  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  51  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  52  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  53  *
  54  * Red Hat Author(s): Behdad Esfahbod
  55  * Google Author(s): Behdad Esfahbod
  56  */
  57 
  58 #ifndef HB_FONT_PRIVATE_HH
  59 #define HB_FONT_PRIVATE_HH
  60 
  61 #include "hb-private.hh"
  62 
  63 #include "hb-object-private.hh"
  64 #include "hb-face-private.hh"
  65 #include "hb-shaper-private.hh"
  66 
  67 
  68 
  69 /*
  70  * hb_font_funcs_t
  71  */
  72 
  73 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
  74   HB_FONT_FUNC_IMPLEMENT (glyph) \
  75   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
  76   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
  77   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
  78   HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
  79   HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
  80   HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
  81   HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
  82   HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
  83   HB_FONT_FUNC_IMPLEMENT (glyph_name) \
  84   HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
  85   /* ^--- Add new callbacks here */
  86 
  87 struct hb_font_funcs_t {
  88   hb_object_header_t header;
  89   ASSERT_POD ();
  90 
  91   hb_bool_t immutable;
  92 
  93   /* Don't access these directly.  Call hb_font_get_*() instead. */
  94 
  95   struct {
  96 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
  97     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
  98 #undef HB_FONT_FUNC_IMPLEMENT
  99   } get;
 100 
 101   struct {
 102 #define HB_FONT_FUNC_IMPLEMENT(name) void *name;
 103     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 104 #undef HB_FONT_FUNC_IMPLEMENT
 105   } user_data;
 106 
 107   struct {
 108 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
 109     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 110 #undef HB_FONT_FUNC_IMPLEMENT
 111   } destroy;
 112 };
 113 
 114 
 115 
 116 /*
 117  * hb_font_t
 118  */
 119 
 120 struct hb_font_t {
 121   hb_object_header_t header;
 122   ASSERT_POD ();
 123 
 124   hb_bool_t immutable;
 125 
 126   hb_font_t *parent;
 127   hb_face_t *face;
 128 
 129   int x_scale;
 130   int y_scale;
 131 
 132   unsigned int x_ppem;
 133   unsigned int y_ppem;
 134 
 135   hb_font_funcs_t   *klass;
 136   void              *user_data;
 137   hb_destroy_func_t  destroy;
 138 
 139   struct hb_shaper_data_t shaper_data;
 140 
 141 
 142   /* Convert from font-space to user-space */
 143   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
 144   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
 145 
 146   /* Convert from parent-font user-space to our user-space */
 147   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
 148     if (unlikely (parent && parent->x_scale != x_scale))
 149       return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
 150     return v;
 151   }
 152   inline hb_position_t parent_scale_y_distance (hb_position_t v) {
 153     if (unlikely (parent && parent->y_scale != y_scale))
 154       return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
 155     return v;
 156   }
 157   inline hb_position_t parent_scale_x_position (hb_position_t v) {
 158     return parent_scale_x_distance (v);
 159   }
 160   inline hb_position_t parent_scale_y_position (hb_position_t v) {
 161     return parent_scale_y_distance (v);
 162   }
 163 
 164   inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
 165     *x = parent_scale_x_distance (*x);
 166     *y = parent_scale_y_distance (*y);
 167   }
 168   inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
 169     *x = parent_scale_x_position (*x);
 170     *y = parent_scale_y_position (*y);
 171   }
 172 
 173 
 174   /* Public getters */
 175 
 176   inline hb_bool_t has_glyph (hb_codepoint_t unicode)
 177   {
 178     hb_codepoint_t glyph;
 179     return get_glyph (unicode, 0, &glyph);
 180   }
 181 
 182   inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 183                               hb_codepoint_t *glyph)
 184   {
 185     *glyph = 0;
 186     return klass->get.glyph (this, user_data,
 187                              unicode, variation_selector, glyph,
 188                              klass->user_data.glyph);
 189   }
 190 
 191   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
 192   {
 193     return klass->get.glyph_h_advance (this, user_data,
 194                                        glyph,
 195                                        klass->user_data.glyph_h_advance);
 196   }
 197 
 198   inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
 199   {
 200     return klass->get.glyph_v_advance (this, user_data,
 201                                        glyph,
 202                                        klass->user_data.glyph_v_advance);
 203   }
 204 
 205   inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
 206                                        hb_position_t *x, hb_position_t *y)
 207   {
 208     *x = *y = 0;
 209     return klass->get.glyph_h_origin (this, user_data,
 210                                       glyph, x, y,
 211                                       klass->user_data.glyph_h_origin);
 212   }
 213 
 214   inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
 215                                        hb_position_t *x, hb_position_t *y)
 216   {
 217     *x = *y = 0;
 218     return klass->get.glyph_v_origin (this, user_data,
 219                                       glyph, x, y,
 220                                       klass->user_data.glyph_v_origin);
 221   }
 222 
 223   inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
 224   {
 225     return klass->get.glyph_h_kerning (this, user_data,
 226                                        left_glyph, right_glyph,
 227                                        klass->user_data.glyph_h_kerning);
 228   }
 229 
 230   inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
 231   {
 232     return klass->get.glyph_v_kerning (this, user_data,
 233                                        top_glyph, bottom_glyph,
 234                                        klass->user_data.glyph_v_kerning);
 235   }
 236 
 237   inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
 238                                       hb_glyph_extents_t *extents)
 239   {
 240     memset (extents, 0, sizeof (*extents));
 241     return klass->get.glyph_extents (this, user_data,
 242                                      glyph,
 243                                      extents,
 244                                      klass->user_data.glyph_extents);
 245   }
 246 
 247   inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
 248                                             hb_position_t *x, hb_position_t *y)
 249   {
 250     *x = *y = 0;
 251     return klass->get.glyph_contour_point (this, user_data,
 252                                            glyph, point_index,
 253                                            x, y,
 254                                            klass->user_data.glyph_contour_point);
 255   }
 256 
 257   inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
 258                                    char *name, unsigned int size)
 259   {
 260     if (size) *name = '\0';
 261     return klass->get.glyph_name (this, user_data,
 262                                   glyph,
 263                                   name, size,
 264                                   klass->user_data.glyph_name);
 265   }
 266 
 267   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
 268                                         hb_codepoint_t *glyph)
 269   {
 270     *glyph = 0;
 271     if (len == -1) len = strlen (name);
 272     return klass->get.glyph_from_name (this, user_data,
 273                                        name, len,
 274                                        glyph,
 275                                        klass->user_data.glyph_from_name);
 276   }
 277 
 278 
 279   /* A bit higher-level, and with fallback */
 280 
 281   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
 282                                                hb_direction_t direction,
 283                                                hb_position_t *x, hb_position_t *y)
 284   {
 285     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
 286       *x = get_glyph_h_advance (glyph);
 287       *y = 0;
 288     } else {
 289       *x = 0;
 290       *y = get_glyph_v_advance (glyph);
 291     }
 292   }
 293 
 294   /* Internal only */
 295   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
 296                                              hb_position_t *x, hb_position_t *y)
 297   {
 298     *x = get_glyph_h_advance (glyph) / 2;
 299 
 300     /* TODO use font_metrics.ascent */
 301     *y = y_scale;
 302   }
 303 
 304   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
 305                                               hb_direction_t direction,
 306                                               hb_position_t *x, hb_position_t *y)
 307   {
 308     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
 309     {
 310       if (!get_glyph_h_origin (glyph, x, y) &&
 311            get_glyph_v_origin (glyph, x, y))
 312       {
 313         hb_position_t dx, dy;
 314         guess_v_origin_minus_h_origin (glyph, &dx, &dy);
 315         *x -= dx; *y -= dy;
 316       }
 317     }
 318     else
 319     {
 320       if (!get_glyph_v_origin (glyph, x, y) &&
 321            get_glyph_h_origin (glyph, x, y))
 322       {
 323         hb_position_t dx, dy;
 324         guess_v_origin_minus_h_origin (glyph, &dx, &dy);
 325         *x += dx; *y += dy;
 326       }
 327     }
 328   }
 329 
 330   inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
 331                                               hb_direction_t direction,
 332                                               hb_position_t *x, hb_position_t *y)
 333   {
 334     hb_position_t origin_x, origin_y;
 335 
 336     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
 337 
 338     *x += origin_x;
 339     *y += origin_y;
 340   }
 341 
 342   inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
 343                                                    hb_direction_t direction,
 344                                                    hb_position_t *x, hb_position_t *y)
 345   {
 346     hb_position_t origin_x, origin_y;
 347 
 348     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
 349 
 350     *x -= origin_x;
 351     *y -= origin_y;
 352   }
 353 
 354   inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
 355                                                hb_direction_t direction,
 356                                                hb_position_t *x, hb_position_t *y)
 357   {
 358     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
 359       *x = get_glyph_h_kerning (first_glyph, second_glyph);
 360       *y = 0;
 361     } else {
 362       *x = 0;
 363       *y = get_glyph_v_kerning (first_glyph, second_glyph);
 364     }
 365   }
 366 
 367   inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
 368                                                  hb_direction_t direction,
 369                                                  hb_glyph_extents_t *extents)
 370   {
 371     hb_bool_t ret = get_glyph_extents (glyph, extents);
 372 
 373     if (ret)
 374       subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
 375 
 376     return ret;
 377   }
 378 
 379   inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
 380                                                        hb_direction_t direction,
 381                                                        hb_position_t *x, hb_position_t *y)
 382   {
 383     hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
 384 
 385     if (ret)
 386       subtract_glyph_origin_for_direction (glyph, direction, x, y);
 387 
 388     return ret;
 389   }
 390 
 391   /* Generates gidDDD if glyph has no name. */
 392   inline void
 393   glyph_to_string (hb_codepoint_t glyph,
 394                    char *s, unsigned int size)
 395   {
 396     if (get_glyph_name (glyph, s, size)) return;
 397 
 398     if (size && snprintf (s, size, "gid%u", glyph) < 0)
 399       *s = '\0';
 400   }
 401 
 402   /* Parses gidDDD and uniUUUU strings automatically. */
 403   inline hb_bool_t
 404   glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
 405                      hb_codepoint_t *glyph)
 406   {
 407     if (get_glyph_from_name (s, len, glyph)) return true;
 408 
 409     if (len == -1) len = strlen (s);
 410 
 411     /* Straight glyph index. */
 412     if (hb_codepoint_parse (s, len, 10, glyph))
 413       return true;
 414 
 415     if (len > 3)
 416     {
 417       /* gidDDD syntax for glyph indices. */
 418       if (0 == strncmp (s, "gid", 3) &&
 419           hb_codepoint_parse (s + 3, len - 3, 10, glyph))
 420         return true;
 421 
 422       /* uniUUUU and other Unicode character indices. */
 423       hb_codepoint_t unichar;
 424       if (0 == strncmp (s, "uni", 3) &&
 425           hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
 426           get_glyph (unichar, 0, glyph))
 427         return true;
 428     }
 429 
 430     return false;
 431   }
 432 
 433   private:
 434   inline hb_position_t em_scale (int16_t v, int scale) { return (hb_position_t) (v * (int64_t) scale / face->get_upem ()); }
 435 };
 436 
 437 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 438 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
 439 #include "hb-shaper-list.hh"
 440 #undef HB_SHAPER_IMPLEMENT
 441 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 442 
 443 
 444 #endif /* HB_FONT_PRIVATE_HH */