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
39 struct hb_ot_font_t
40 {
41 unsigned int num_glyphs;
42 unsigned int num_hmetrics;
43 const OT::hmtx *hmtx;
44 hb_blob_t *hmtx_blob;
45
46 const OT::CmapSubtable *cmap;
47 const OT::CmapSubtable *cmap_uvs;
48 hb_blob_t *cmap_blob;
49 };
50
51
52 static hb_ot_font_t *
_hb_ot_font_create(hb_font_t * font)53 _hb_ot_font_create (hb_font_t *font)
54 {
55 hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
56
57 if (unlikely (!ot_font))
58 return NULL;
59
60 ot_font->num_glyphs = font->face->get_num_glyphs ();
61
62 {
63 hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
64 const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
65 ot_font->num_hmetrics = hhea->numberOfHMetrics;
66 hb_blob_destroy (hhea_blob);
67 }
68 ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx));
69 if (unlikely (!ot_font->num_hmetrics ||
70 2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob)))
71 {
72 hb_blob_destroy (ot_font->hmtx_blob);
73 free (ot_font);
74 return NULL;
75 }
76 ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
77
78 ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap));
79 const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (ot_font->cmap_blob);
80 const OT::CmapSubtable *subtable = NULL;
81 const OT::CmapSubtable *subtable_uvs = NULL;
82
83 /* 32-bit subtables. */
84 if (!subtable) subtable = cmap->find_subtable (3, 10);
85 if (!subtable) subtable = cmap->find_subtable (0, 6);
86 if (!subtable) subtable = cmap->find_subtable (0, 4);
87 /* 16-bit subtables. */
88 if (!subtable) subtable = cmap->find_subtable (3, 1);
89 if (!subtable) subtable = cmap->find_subtable (0, 3);
90 if (!subtable) subtable = cmap->find_subtable (0, 2);
91 if (!subtable) subtable = cmap->find_subtable (0, 1);
92 if (!subtable) subtable = cmap->find_subtable (0, 0);
93 /* Meh. */
94 if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
95
96 /* UVS subtable. */
97 if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
98 /* Meh. */
99 if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
100
101 ot_font->cmap = subtable;
102 ot_font->cmap_uvs = subtable_uvs;
103
104 return ot_font;
105 }
106
107 static void
_hb_ot_font_destroy(hb_ot_font_t * ot_font)108 _hb_ot_font_destroy (hb_ot_font_t *ot_font)
109 {
110 hb_blob_destroy (ot_font->cmap_blob);
111 hb_blob_destroy (ot_font->hmtx_blob);
112
113 free (ot_font);
114 }
115
116
117 static hb_bool_t
hb_ot_get_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)118 hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
119 void *font_data,
120 hb_codepoint_t unicode,
121 hb_codepoint_t variation_selector,
122 hb_codepoint_t *glyph,
123 void *user_data HB_UNUSED)
124
125 {
126 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
127
128 if (unlikely (variation_selector))
129 {
130 switch (ot_font->cmap_uvs->get_glyph_variant (unicode,
131 variation_selector,
132 glyph))
133 {
134 case OT::GLYPH_VARIANT_NOT_FOUND: return false;
135 case OT::GLYPH_VARIANT_FOUND: return true;
136 case OT::GLYPH_VARIANT_USE_DEFAULT: break;
137 }
138 }
139
140 return ot_font->cmap->get_glyph (unicode, glyph);
141 }
142
143 static hb_position_t
hb_ot_get_glyph_h_advance(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t glyph,void * user_data HB_UNUSED)144 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
145 void *font_data,
146 hb_codepoint_t glyph,
147 void *user_data HB_UNUSED)
148 {
149 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
150
151 if (unlikely (glyph >= ot_font->num_glyphs))
152 return 0; /* Maybe better to return notdef's advance instead? */
153
154 if (glyph >= ot_font->num_hmetrics)
155 glyph = ot_font->num_hmetrics - 1;
156
157 return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth);
158 }
159
160 static hb_position_t
hb_ot_get_glyph_v_advance(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t glyph,void * user_data HB_UNUSED)161 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
162 void *font_data,
163 hb_codepoint_t glyph,
164 void *user_data HB_UNUSED)
165 {
166 /* TODO */
167 return 0;
168 }
169
170 static hb_bool_t
hb_ot_get_glyph_h_origin(hb_font_t * font HB_UNUSED,void * font_data HB_UNUSED,hb_codepoint_t glyph HB_UNUSED,hb_position_t * x HB_UNUSED,hb_position_t * y HB_UNUSED,void * user_data HB_UNUSED)171 hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
172 void *font_data HB_UNUSED,
173 hb_codepoint_t glyph HB_UNUSED,
174 hb_position_t *x HB_UNUSED,
175 hb_position_t *y HB_UNUSED,
176 void *user_data HB_UNUSED)
177 {
178 /* We always work in the horizontal coordinates. */
179 return true;
180 }
181
182 static hb_bool_t
hb_ot_get_glyph_v_origin(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t glyph,hb_position_t * x,hb_position_t * y,void * user_data HB_UNUSED)183 hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
184 void *font_data,
185 hb_codepoint_t glyph,
186 hb_position_t *x,
187 hb_position_t *y,
188 void *user_data HB_UNUSED)
189 {
190 /* TODO */
191 return false;
192 }
193
194 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)195 hb_ot_get_glyph_h_kerning (hb_font_t *font,
196 void *font_data,
197 hb_codepoint_t left_glyph,
198 hb_codepoint_t right_glyph,
199 void *user_data HB_UNUSED)
200 {
201 /* TODO */
202 return 0;
203 }
204
205 static hb_position_t
hb_ot_get_glyph_v_kerning(hb_font_t * font HB_UNUSED,void * font_data HB_UNUSED,hb_codepoint_t top_glyph HB_UNUSED,hb_codepoint_t bottom_glyph HB_UNUSED,void * user_data HB_UNUSED)206 hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
207 void *font_data HB_UNUSED,
208 hb_codepoint_t top_glyph HB_UNUSED,
209 hb_codepoint_t bottom_glyph HB_UNUSED,
210 void *user_data HB_UNUSED)
211 {
212 return 0;
213 }
214
215 static hb_bool_t
hb_ot_get_glyph_extents(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t glyph,hb_glyph_extents_t * extents,void * user_data HB_UNUSED)216 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
217 void *font_data,
218 hb_codepoint_t glyph,
219 hb_glyph_extents_t *extents,
220 void *user_data HB_UNUSED)
221 {
222 /* TODO */
223 return false;
224 }
225
226 static hb_bool_t
hb_ot_get_glyph_contour_point(hb_font_t * font HB_UNUSED,void * font_data,hb_codepoint_t glyph,unsigned int point_index,hb_position_t * x,hb_position_t * y,void * user_data HB_UNUSED)227 hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
228 void *font_data,
229 hb_codepoint_t glyph,
230 unsigned int point_index,
231 hb_position_t *x,
232 hb_position_t *y,
233 void *user_data HB_UNUSED)
234 {
235 /* TODO */
236 return false;
237 }
238
239 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)240 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
241 void *font_data,
242 hb_codepoint_t glyph,
243 char *name, unsigned int size,
244 void *user_data HB_UNUSED)
245 {
246 /* TODO */
247 return false;
248 }
249
250 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)251 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
252 void *font_data,
253 const char *name, int len, /* -1 means nul-terminated */
254 hb_codepoint_t *glyph,
255 void *user_data HB_UNUSED)
256 {
257 /* TODO */
258 return false;
259 }
260
261
262 static hb_font_funcs_t *
_hb_ot_get_font_funcs(void)263 _hb_ot_get_font_funcs (void)
264 {
265 static const hb_font_funcs_t ot_ffuncs = {
266 HB_OBJECT_HEADER_STATIC,
267
268 true, /* immutable */
269
270 {
271 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
272 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
273 #undef HB_FONT_FUNC_IMPLEMENT
274 }
275 };
276
277 return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
278 }
279
280
281 void
hb_ot_font_set_funcs(hb_font_t * font)282 hb_ot_font_set_funcs (hb_font_t *font)
283 {
284 hb_ot_font_t *ot_font = _hb_ot_font_create (font);
285 if (unlikely (!ot_font))
286 return;
287
288 hb_font_set_funcs (font,
289 _hb_ot_get_font_funcs (),
290 ot_font,
291 (hb_destroy_func_t) _hb_ot_font_destroy);
292 }
293