• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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