Revert "Imported Upstream version 1.2.7"
[platform/upstream/harfbuzz.git] / src / hb-ot-font.cc
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-hhea-table.hh"
35 #include "hb-ot-hmtx-table.hh"
36
37
38 struct hb_ot_face_metrics_accelerator_t
39 {
40   unsigned int num_metrics;
41   unsigned int num_advances;
42   unsigned int default_advance;
43   const OT::_mtx *table;
44   hb_blob_t *blob;
45
46   inline void init (hb_face_t *face,
47                     hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
48                     unsigned int default_advance)
49   {
50     this->default_advance = default_advance;
51     this->num_metrics = face->get_num_glyphs ();
52
53     hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
54     const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
55     this->num_advances = _hea->numberOfLongMetrics;
56     hb_blob_destroy (_hea_blob);
57
58     this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
59     if (unlikely (!this->num_advances ||
60                   2 * (this->num_advances + this->num_metrics) < hb_blob_get_length (this->blob)))
61     {
62       this->num_metrics = this->num_advances = 0;
63       hb_blob_destroy (this->blob);
64       this->blob = hb_blob_get_empty ();
65     }
66     this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
67   }
68
69   inline void fini (void)
70   {
71     hb_blob_destroy (this->blob);
72   }
73
74   inline unsigned int get_advance (hb_codepoint_t glyph) const
75   {
76     if (unlikely (glyph >= this->num_metrics))
77     {
78       /* If this->num_metrics is zero, it means we don't have the metrics table
79        * for this direction: return one EM.  Otherwise, it means that the glyph
80        * index is out of bound: return zero. */
81       if (this->num_metrics)
82         return 0;
83       else
84         return this->default_advance;
85     }
86
87     if (glyph >= this->num_advances)
88       glyph = this->num_advances - 1;
89
90     return this->table->longMetric[glyph].advance;
91   }
92 };
93
94 struct hb_ot_face_cmap_accelerator_t
95 {
96   const OT::CmapSubtable *table;
97   const OT::CmapSubtable *uvs_table;
98   hb_blob_t *blob;
99
100   inline void init (hb_face_t *face)
101   {
102     this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
103     const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
104     const OT::CmapSubtable *subtable = NULL;
105     const OT::CmapSubtable *subtable_uvs = NULL;
106
107     /* 32-bit subtables. */
108     if (!subtable) subtable = cmap->find_subtable (3, 10);
109     if (!subtable) subtable = cmap->find_subtable (0, 6);
110     if (!subtable) subtable = cmap->find_subtable (0, 4);
111     /* 16-bit subtables. */
112     if (!subtable) subtable = cmap->find_subtable (3, 1);
113     if (!subtable) subtable = cmap->find_subtable (0, 3);
114     if (!subtable) subtable = cmap->find_subtable (0, 2);
115     if (!subtable) subtable = cmap->find_subtable (0, 1);
116     if (!subtable) subtable = cmap->find_subtable (0, 0);
117     /* Meh. */
118     if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
119
120     /* UVS subtable. */
121     if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
122     /* Meh. */
123     if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
124
125     this->table = subtable;
126     this->uvs_table = subtable_uvs;
127   }
128
129   inline void fini (void)
130   {
131     hb_blob_destroy (this->blob);
132   }
133
134   inline bool get_glyph (hb_codepoint_t  unicode,
135                          hb_codepoint_t  variation_selector,
136                          hb_codepoint_t *glyph) const
137   {
138     if (unlikely (variation_selector))
139     {
140       switch (this->uvs_table->get_glyph_variant (unicode,
141                                                   variation_selector,
142                                                   glyph))
143       {
144         case OT::GLYPH_VARIANT_NOT_FOUND:       return false;
145         case OT::GLYPH_VARIANT_FOUND:           return true;
146         case OT::GLYPH_VARIANT_USE_DEFAULT:     break;
147       }
148     }
149
150     return this->table->get_glyph (unicode, glyph);
151   }
152 };
153
154
155 struct hb_ot_font_t
156 {
157   hb_ot_face_cmap_accelerator_t cmap;
158   hb_ot_face_metrics_accelerator_t h_metrics;
159   hb_ot_face_metrics_accelerator_t v_metrics;
160 };
161
162
163 static hb_ot_font_t *
164 _hb_ot_font_create (hb_font_t *font)
165 {
166   hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
167   hb_face_t *face = font->face;
168
169   if (unlikely (!ot_font))
170     return NULL;
171
172   unsigned int upem = face->get_upem ();
173
174   ot_font->cmap.init (face);
175   ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
176   ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */
177
178   return ot_font;
179 }
180
181 static void
182 _hb_ot_font_destroy (hb_ot_font_t *ot_font)
183 {
184   ot_font->cmap.fini ();
185   ot_font->h_metrics.fini ();
186   ot_font->v_metrics.fini ();
187
188   free (ot_font);
189 }
190
191
192 static hb_bool_t
193 hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
194                  void *font_data,
195                  hb_codepoint_t unicode,
196                  hb_codepoint_t variation_selector,
197                  hb_codepoint_t *glyph,
198                  void *user_data HB_UNUSED)
199
200 {
201   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
202   return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
203 }
204
205 static hb_position_t
206 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
207                            void *font_data,
208                            hb_codepoint_t glyph,
209                            void *user_data HB_UNUSED)
210 {
211   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
212   return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
213 }
214
215 static hb_position_t
216 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
217                            void *font_data,
218                            hb_codepoint_t glyph,
219                            void *user_data HB_UNUSED)
220 {
221   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
222   return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph));
223 }
224
225 static hb_bool_t
226 hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
227                           void *font_data HB_UNUSED,
228                           hb_codepoint_t glyph HB_UNUSED,
229                           hb_position_t *x HB_UNUSED,
230                           hb_position_t *y HB_UNUSED,
231                           void *user_data HB_UNUSED)
232 {
233   /* We always work in the horizontal coordinates. */
234   return true;
235 }
236
237 static hb_bool_t
238 hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
239                           void *font_data,
240                           hb_codepoint_t glyph,
241                           hb_position_t *x,
242                           hb_position_t *y,
243                           void *user_data HB_UNUSED)
244 {
245   /* TODO */
246   return false;
247 }
248
249 static hb_position_t
250 hb_ot_get_glyph_h_kerning (hb_font_t *font,
251                            void *font_data,
252                            hb_codepoint_t left_glyph,
253                            hb_codepoint_t right_glyph,
254                            void *user_data HB_UNUSED)
255 {
256   /* TODO */
257   return 0;
258 }
259
260 static hb_position_t
261 hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
262                            void *font_data HB_UNUSED,
263                            hb_codepoint_t top_glyph HB_UNUSED,
264                            hb_codepoint_t bottom_glyph HB_UNUSED,
265                            void *user_data HB_UNUSED)
266 {
267   /* OpenType doesn't have vertical-kerning other than GPOS. */
268   return 0;
269 }
270
271 static hb_bool_t
272 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
273                          void *font_data,
274                          hb_codepoint_t glyph,
275                          hb_glyph_extents_t *extents,
276                          void *user_data HB_UNUSED)
277 {
278   /* TODO */
279   return false;
280 }
281
282 static hb_bool_t
283 hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
284                                void *font_data,
285                                hb_codepoint_t glyph,
286                                unsigned int point_index,
287                                hb_position_t *x,
288                                hb_position_t *y,
289                                void *user_data HB_UNUSED)
290 {
291   /* TODO */
292   return false;
293 }
294
295 static hb_bool_t
296 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
297                       void *font_data,
298                       hb_codepoint_t glyph,
299                       char *name, unsigned int size,
300                       void *user_data HB_UNUSED)
301 {
302   /* TODO */
303   return false;
304 }
305
306 static hb_bool_t
307 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
308                            void *font_data,
309                            const char *name, int len, /* -1 means nul-terminated */
310                            hb_codepoint_t *glyph,
311                            void *user_data HB_UNUSED)
312 {
313   /* TODO */
314   return false;
315 }
316
317
318 static hb_font_funcs_t *
319 _hb_ot_get_font_funcs (void)
320 {
321   static const hb_font_funcs_t ot_ffuncs = {
322     HB_OBJECT_HEADER_STATIC,
323
324     true, /* immutable */
325
326     {
327 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
328       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
329 #undef HB_FONT_FUNC_IMPLEMENT
330     }
331   };
332
333   return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
334 }
335
336
337 void
338 hb_ot_font_set_funcs (hb_font_t *font)
339 {
340   hb_ot_font_t *ot_font = _hb_ot_font_create (font);
341   if (unlikely (!ot_font))
342     return;
343
344   hb_font_set_funcs (font,
345                      _hb_ot_get_font_funcs (),
346                      ot_font,
347                      (hb_destroy_func_t) _hb_ot_font_destroy);
348 }