hb-ot-font.cc 9.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * Copyright © 2011,2014  Google, Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
 */

#include "hb-private.hh"

#include "hb-ot.h"

#include "hb-font-private.hh"

33
#include "hb-ot-cmap-table.hh"
34
#include "hb-ot-glyf-table.hh"
35
#include "hb-ot-hmtx-table.hh"
36
#include "hb-ot-kern-table.hh"
37
#include "hb-ot-post-table.hh"
38

39 40
#include "hb-ot-color-cbdt-table.hh"

41 42 43

struct hb_ot_font_t
{
B
Behdad Esfahbod 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
  inline void init (hb_face_t *face)
  {
    cmap.init (face);
    h_metrics.init (face);
    v_metrics.init (face, h_metrics.ascender - h_metrics.descender); /* TODO Can we do this lazily? */

    this->face = face;
    glyf.init ();
    cbdt.init ();
    post.init ();
    kern.init ();
  }
  inline void fini (void)
  {
    cmap.fini ();
    h_metrics.fini ();
    v_metrics.fini ();

    glyf.fini ();
    cbdt.fini ();
    post.fini ();
    kern.fini ();
  }

68
  OT::cmap::accelerator_t cmap;
69 70
  OT::hmtx::accelerator_t h_metrics;
  OT::vmtx::accelerator_t v_metrics;
71

B
Minor  
Behdad Esfahbod 已提交
72
  hb_face_t *face; /* MUST be JUST before the lazy loaders. */
B
Rename  
Behdad Esfahbod 已提交
73 74 75 76
  hb_object_lazy_loader_t<1, OT::glyf::accelerator_t> glyf;
  hb_object_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt;
  hb_object_lazy_loader_t<3, OT::post::accelerator_t> post;
  hb_object_lazy_loader_t<4, OT::kern::accelerator_t> kern;
77 78 79 80
};


static hb_ot_font_t *
B
Minor  
Behdad Esfahbod 已提交
81
_hb_ot_font_create (hb_face_t *face)
82 83 84 85
{
  hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));

  if (unlikely (!ot_font))
B
Behdad Esfahbod 已提交
86
    return nullptr;
87

B
Behdad Esfahbod 已提交
88
  ot_font->init (face);
89

90 91 92 93
  return ot_font;
}

static void
94
_hb_ot_font_destroy (void *data)
95
{
96 97
  hb_ot_font_t *ot_font = (hb_ot_font_t *) data;

B
Behdad Esfahbod 已提交
98
  ot_font->fini ();
99 100 101 102 103 104

  free (ot_font);
}


static hb_bool_t
105 106 107 108 109 110 111 112 113 114
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
			 void *font_data,
			 hb_codepoint_t unicode,
			 hb_codepoint_t *glyph,
			 void *user_data HB_UNUSED)

{
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
  return ot_font->cmap.get_nominal_glyph (unicode, glyph);
}
115

116 117 118 119 120 121 122
static hb_bool_t
hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
			   void *font_data,
			   hb_codepoint_t unicode,
			   hb_codepoint_t variation_selector,
			   hb_codepoint_t *glyph,
			   void *user_data HB_UNUSED)
123
{
124
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
125
  return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
126 127 128
}

static hb_position_t
129
hb_ot_get_glyph_h_advance (hb_font_t *font,
130 131 132 133 134
			   void *font_data,
			   hb_codepoint_t glyph,
			   void *user_data HB_UNUSED)
{
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
135
  return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font));
136 137 138
}

static hb_position_t
139
hb_ot_get_glyph_v_advance (hb_font_t *font,
140 141 142 143
			   void *font_data,
			   hb_codepoint_t glyph,
			   void *user_data HB_UNUSED)
{
144
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
145
  return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
146 147
}

B
Behdad Esfahbod 已提交
148 149 150 151 152 153 154 155 156 157 158
static hb_position_t
hb_ot_get_glyph_h_kerning (hb_font_t *font,
			   void *font_data,
			   hb_codepoint_t left_glyph,
			   hb_codepoint_t right_glyph,
			   void *user_data HB_UNUSED)
{
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
  return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph));
}

159
static hb_bool_t
160
hb_ot_get_glyph_extents (hb_font_t *font,
161 162 163 164 165
			 void *font_data,
			 hb_codepoint_t glyph,
			 hb_glyph_extents_t *extents,
			 void *user_data HB_UNUSED)
{
166
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
167
  bool ret = ot_font->glyf->get_extents (glyph, extents);
168
  if (!ret)
169
    ret = ot_font->cbdt->get_extents (glyph, extents);
170
  // TODO Hook up side-bearings variations.
171 172 173 174 175
  extents->x_bearing = font->em_scale_x (extents->x_bearing);
  extents->y_bearing = font->em_scale_y (extents->y_bearing);
  extents->width     = font->em_scale_x (extents->width);
  extents->height    = font->em_scale_y (extents->height);
  return ret;
176 177
}

178 179 180 181 182 183 184 185 186 187 188
static hb_bool_t
hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
                      void *font_data,
                      hb_codepoint_t glyph,
                      char *name, unsigned int size,
                      void *user_data HB_UNUSED)
{
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
  return ot_font->post->get_glyph_name (glyph, name, size);
}

189 190 191 192 193 194 195 196 197 198 199
static hb_bool_t
hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
                           void *font_data,
                           const char *name, int len,
                           hb_codepoint_t *glyph,
                           void *user_data HB_UNUSED)
{
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
  return ot_font->post->get_glyph_from_name (name, len, glyph);
}

200
static hb_bool_t
201
hb_ot_get_font_h_extents (hb_font_t *font,
202 203 204 205 206 207 208 209
			  void *font_data,
			  hb_font_extents_t *metrics,
			  void *user_data HB_UNUSED)
{
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
  metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
  metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
  metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
210
  // TODO Hook up variations.
B
Behdad Esfahbod 已提交
211
  return ot_font->h_metrics.has_font_extents;
212 213 214
}

static hb_bool_t
215
hb_ot_get_font_v_extents (hb_font_t *font,
216 217 218 219 220 221 222 223
			  void *font_data,
			  hb_font_extents_t *metrics,
			  void *user_data HB_UNUSED)
{
  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
  metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
  metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
  metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
224
  // TODO Hook up variations.
B
Behdad Esfahbod 已提交
225
  return ot_font->v_metrics.has_font_extents;
226
}
227

228
static hb_atomic_ptr_t <hb_font_funcs_t> static_ot_funcs;
229 230 231 232 233

#ifdef HB_USE_ATEXIT
static
void free_static_ot_funcs (void)
{
234
retry:
235 236
  hb_font_funcs_t *ot_funcs = static_ot_funcs.get ();
  if (unlikely (!static_ot_funcs.cmpexch (ot_funcs, nullptr)))
237 238 239
    goto retry;

  hb_font_funcs_destroy (ot_funcs);
240 241 242
}
#endif

243 244 245
static hb_font_funcs_t *
_hb_ot_get_font_funcs (void)
{
246
retry:
247
  hb_font_funcs_t *funcs = static_ot_funcs.get ();
248

249 250 251 252
  if (unlikely (!funcs))
  {
    funcs = hb_font_funcs_create ();

B
Behdad Esfahbod 已提交
253 254 255 256 257 258 259 260
    hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
    hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
    hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr);
    hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
    //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
    //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
261
    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
B
Behdad Esfahbod 已提交
262 263
    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr);
    hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
B
Behdad Esfahbod 已提交
264
    //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
265
    hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
266
    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
267 268 269

    hb_font_funcs_make_immutable (funcs);

270 271
    if (unlikely (!static_ot_funcs.cmpexch (nullptr, funcs)))
    {
272 273
      hb_font_funcs_destroy (funcs);
      goto retry;
274
    }
275 276 277 278

#ifdef HB_USE_ATEXIT
    atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
#endif
279 280
  };

281
  return funcs;
282 283 284
}


S
Sascha Brawer 已提交
285
/**
B
Behdad Esfahbod 已提交
286 287
 * hb_ot_font_set_funcs:
 *
S
Sascha Brawer 已提交
288 289
 * Since: 0.9.28
 **/
290 291 292
void
hb_ot_font_set_funcs (hb_font_t *font)
{
B
Minor  
Behdad Esfahbod 已提交
293
  hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
294 295 296 297 298 299
  if (unlikely (!ot_font))
    return;

  hb_font_set_funcs (font,
		     _hb_ot_get_font_funcs (),
		     ot_font,
300
		     _hb_ot_font_destroy);
301
}