OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2011,2014 Google, Inc. | 2 * Copyright © 2011,2014 Google, Inc. |
3 * | 3 * |
4 * This is part of HarfBuzz, a text shaping library. | 4 * This is part of HarfBuzz, a text shaping library. |
5 * | 5 * |
6 * Permission is hereby granted, without written agreement and without | 6 * Permission is hereby granted, without written agreement and without |
7 * license or royalty fees, to use, copy, modify, and distribute this | 7 * license or royalty fees, to use, copy, modify, and distribute this |
8 * software and its documentation for any purpose, provided that the | 8 * software and its documentation for any purpose, provided that the |
9 * above copyright notice and the following two paragraphs appear in | 9 * above copyright notice and the following two paragraphs appear in |
10 * all copies of this software. | 10 * all copies of this software. |
(...skipping 17 matching lines...) Expand all Loading... |
28 | 28 |
29 #include "hb-ot.h" | 29 #include "hb-ot.h" |
30 | 30 |
31 #include "hb-font-private.hh" | 31 #include "hb-font-private.hh" |
32 | 32 |
33 #include "hb-ot-cmap-table.hh" | 33 #include "hb-ot-cmap-table.hh" |
34 #include "hb-ot-hhea-table.hh" | 34 #include "hb-ot-hhea-table.hh" |
35 #include "hb-ot-hmtx-table.hh" | 35 #include "hb-ot-hmtx-table.hh" |
36 | 36 |
37 | 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_ta
ble (_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_len
gth (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 |
38 | 154 |
39 struct hb_ot_font_t | 155 struct hb_ot_font_t |
40 { | 156 { |
41 unsigned int num_glyphs; | 157 hb_ot_face_cmap_accelerator_t cmap; |
42 unsigned int num_hmetrics; | 158 hb_ot_face_metrics_accelerator_t h_metrics; |
43 const OT::hmtx *hmtx; | 159 hb_ot_face_metrics_accelerator_t v_metrics; |
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 }; | 160 }; |
50 | 161 |
51 | 162 |
52 static hb_ot_font_t * | 163 static hb_ot_font_t * |
53 _hb_ot_font_create (hb_font_t *font) | 164 _hb_ot_font_create (hb_font_t *font) |
54 { | 165 { |
55 hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); | 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; |
56 | 168 |
57 if (unlikely (!ot_font)) | 169 if (unlikely (!ot_font)) |
58 return NULL; | 170 return NULL; |
59 | 171 |
60 ot_font->num_glyphs = font->face->get_num_glyphs (); | 172 unsigned int upem = face->get_upem (); |
61 | 173 |
62 { | 174 ot_font->cmap.init (face); |
63 hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->refere
nce_table (HB_OT_TAG_hhea)); | 175 ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); |
64 const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob); | 176 ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO
Can we do this lazily? */ |
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_b
lob); | |
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 | 177 |
104 return ot_font; | 178 return ot_font; |
105 } | 179 } |
106 | 180 |
107 static void | 181 static void |
108 _hb_ot_font_destroy (hb_ot_font_t *ot_font) | 182 _hb_ot_font_destroy (hb_ot_font_t *ot_font) |
109 { | 183 { |
110 hb_blob_destroy (ot_font->cmap_blob); | 184 ot_font->cmap.fini (); |
111 hb_blob_destroy (ot_font->hmtx_blob); | 185 ot_font->h_metrics.fini (); |
| 186 ot_font->v_metrics.fini (); |
112 | 187 |
113 free (ot_font); | 188 free (ot_font); |
114 } | 189 } |
115 | 190 |
116 | 191 |
117 static hb_bool_t | 192 static hb_bool_t |
118 hb_ot_get_glyph (hb_font_t *font HB_UNUSED, | 193 hb_ot_get_glyph (hb_font_t *font HB_UNUSED, |
119 void *font_data, | 194 void *font_data, |
120 hb_codepoint_t unicode, | 195 hb_codepoint_t unicode, |
121 hb_codepoint_t variation_selector, | 196 hb_codepoint_t variation_selector, |
122 hb_codepoint_t *glyph, | 197 hb_codepoint_t *glyph, |
123 void *user_data HB_UNUSED) | 198 void *user_data HB_UNUSED) |
124 | 199 |
125 { | 200 { |
126 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; | 201 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; |
127 | 202 return ot_font->cmap.get_glyph (unicode, variation_selector, glyph); |
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 } | 203 } |
142 | 204 |
143 static hb_position_t | 205 static hb_position_t |
144 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, | 206 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, |
145 void *font_data, | 207 void *font_data, |
146 hb_codepoint_t glyph, | 208 hb_codepoint_t glyph, |
147 void *user_data HB_UNUSED) | 209 void *user_data HB_UNUSED) |
148 { | 210 { |
149 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; | 211 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; |
150 | 212 return font->em_scale_x (ot_font->h_metrics.get_advance (glyph)); |
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 } | 213 } |
159 | 214 |
160 static hb_position_t | 215 static hb_position_t |
161 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, | 216 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, |
162 void *font_data, | 217 void *font_data, |
163 hb_codepoint_t glyph, | 218 hb_codepoint_t glyph, |
164 void *user_data HB_UNUSED) | 219 void *user_data HB_UNUSED) |
165 { | 220 { |
166 /* TODO */ | 221 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; |
167 return 0; | 222 return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph)); |
168 } | 223 } |
169 | 224 |
170 static hb_bool_t | 225 static hb_bool_t |
171 hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED, | 226 hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED, |
172 void *font_data HB_UNUSED, | 227 void *font_data HB_UNUSED, |
173 hb_codepoint_t glyph HB_UNUSED, | 228 hb_codepoint_t glyph HB_UNUSED, |
174 hb_position_t *x HB_UNUSED, | 229 hb_position_t *x HB_UNUSED, |
175 hb_position_t *y HB_UNUSED, | 230 hb_position_t *y HB_UNUSED, |
176 void *user_data HB_UNUSED) | 231 void *user_data HB_UNUSED) |
177 { | 232 { |
(...skipping 24 matching lines...) Expand all Loading... |
202 return 0; | 257 return 0; |
203 } | 258 } |
204 | 259 |
205 static hb_position_t | 260 static hb_position_t |
206 hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, | 261 hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, |
207 void *font_data HB_UNUSED, | 262 void *font_data HB_UNUSED, |
208 hb_codepoint_t top_glyph HB_UNUSED, | 263 hb_codepoint_t top_glyph HB_UNUSED, |
209 hb_codepoint_t bottom_glyph HB_UNUSED, | 264 hb_codepoint_t bottom_glyph HB_UNUSED, |
210 void *user_data HB_UNUSED) | 265 void *user_data HB_UNUSED) |
211 { | 266 { |
| 267 /* OpenType doesn't have vertical-kerning other than GPOS. */ |
212 return 0; | 268 return 0; |
213 } | 269 } |
214 | 270 |
215 static hb_bool_t | 271 static hb_bool_t |
216 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, | 272 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, |
217 void *font_data, | 273 void *font_data, |
218 hb_codepoint_t glyph, | 274 hb_codepoint_t glyph, |
219 hb_glyph_extents_t *extents, | 275 hb_glyph_extents_t *extents, |
220 void *user_data HB_UNUSED) | 276 void *user_data HB_UNUSED) |
221 { | 277 { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 { | 339 { |
284 hb_ot_font_t *ot_font = _hb_ot_font_create (font); | 340 hb_ot_font_t *ot_font = _hb_ot_font_create (font); |
285 if (unlikely (!ot_font)) | 341 if (unlikely (!ot_font)) |
286 return; | 342 return; |
287 | 343 |
288 hb_font_set_funcs (font, | 344 hb_font_set_funcs (font, |
289 _hb_ot_get_font_funcs (), | 345 _hb_ot_get_font_funcs (), |
290 ot_font, | 346 ot_font, |
291 (hb_destroy_func_t) _hb_ot_font_destroy); | 347 (hb_destroy_func_t) _hb_ot_font_destroy); |
292 } | 348 } |
OLD | NEW |