OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2011 Google, Inc. | 2 * Copyright © 2011,2012 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. |
11 * | 11 * |
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | 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 | 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
16 * DAMAGE. | 16 * DAMAGE. |
17 * | 17 * |
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | 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 | 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
23 * | 23 * |
24 * Google Author(s): Behdad Esfahbod | 24 * Google Author(s): Behdad Esfahbod |
25 */ | 25 */ |
26 | 26 |
27 #define _WIN32_WINNT 0x0500 | 27 #define _WIN32_WINNT 0x0600 |
| 28 #define WIN32_LEAN_AND_MEAN |
28 | 29 |
29 #include "hb-private.hh" | 30 #define HB_SHAPER uniscribe |
| 31 #include "hb-shaper-impl-private.hh" |
30 | 32 |
31 #include <windows.h> | 33 #include <windows.h> |
32 #include <usp10.h> | 34 #include <usp10.h> |
33 | 35 |
34 typedef ULONG WIN_ULONG; | |
35 | |
36 #include "hb-uniscribe.h" | 36 #include "hb-uniscribe.h" |
37 | 37 |
38 #include "hb-ot-name-table.hh" | 38 #include "hb-ot-name-table.hh" |
39 #include "hb-ot-tag.h" | 39 #include "hb-ot-tag.h" |
40 | 40 |
41 #include "hb-font-private.hh" | |
42 #include "hb-buffer-private.hh" | |
43 | |
44 | |
45 | 41 |
46 #ifndef HB_DEBUG_UNISCRIBE | 42 #ifndef HB_DEBUG_UNISCRIBE |
47 #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0) | 43 #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0) |
48 #endif | 44 #endif |
49 | 45 |
50 | 46 |
51 /* | 47 /* |
52 DWORD GetFontData( | 48 DWORD GetFontData( |
53 __in HDC hdc, | 49 __in HDC hdc, |
54 __in DWORD dwTable, | 50 __in DWORD dwTable, |
55 __in DWORD dwOffset, | 51 __in DWORD dwOffset, |
56 __out LPVOID lpvBuffer, | 52 __out LPVOID lpvBuffer, |
57 __in DWORD cbData | 53 __in DWORD cbData |
58 ); | 54 ); |
59 */ | 55 */ |
60 | 56 |
| 57 |
| 58 HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face) |
| 59 HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font) |
| 60 |
| 61 |
| 62 /* |
| 63 * shaper face data |
| 64 */ |
| 65 |
| 66 struct hb_uniscribe_shaper_face_data_t { |
| 67 HANDLE fh; |
| 68 }; |
| 69 |
| 70 hb_uniscribe_shaper_face_data_t * |
| 71 _hb_uniscribe_shaper_face_data_create (hb_face_t *face) |
| 72 { |
| 73 hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) ca
lloc (1, sizeof (hb_uniscribe_shaper_face_data_t)); |
| 74 if (unlikely (!data)) |
| 75 return NULL; |
| 76 |
| 77 hb_blob_t *blob = hb_face_reference_blob (face); |
| 78 unsigned int blob_length; |
| 79 const char *blob_data = hb_blob_get_data (blob, &blob_length); |
| 80 if (unlikely (!blob_length)) |
| 81 DEBUG_MSG (UNISCRIBE, face, "Face has empty blob"); |
| 82 |
| 83 DWORD num_fonts_installed; |
| 84 data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_font
s_installed); |
| 85 hb_blob_destroy (blob); |
| 86 if (unlikely (!data->fh)) { |
| 87 DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed"); |
| 88 free (data); |
| 89 return NULL; |
| 90 } |
| 91 |
| 92 return data; |
| 93 } |
| 94 |
| 95 void |
| 96 _hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data) |
| 97 { |
| 98 RemoveFontMemResourceEx (data->fh); |
| 99 free (data); |
| 100 } |
| 101 |
| 102 |
| 103 /* |
| 104 * shaper font data |
| 105 */ |
| 106 |
| 107 struct hb_uniscribe_shaper_font_data_t { |
| 108 HDC hdc; |
| 109 LOGFONTW log_font; |
| 110 HFONT hfont; |
| 111 SCRIPT_CACHE script_cache; |
| 112 }; |
| 113 |
61 static bool | 114 static bool |
62 populate_log_font (LOGFONTW *lf, | 115 populate_log_font (LOGFONTW *lf, |
63 HDC hdc, | |
64 hb_font_t *font) | 116 hb_font_t *font) |
65 { | 117 { |
66 memset (lf, 0, sizeof (*lf)); | 118 memset (lf, 0, sizeof (*lf)); |
67 int dpi = GetDeviceCaps (hdc, LOGPIXELSY); | |
68 lf->lfHeight = -font->y_scale; | 119 lf->lfHeight = -font->y_scale; |
| 120 lf->lfCharSet = DEFAULT_CHARSET; |
69 | 121 |
70 hb_blob_t *blob = Sanitizer<name>::sanitize (hb_face_reference_table (font->fa
ce, HB_TAG ('n','a','m','e'))); | 122 hb_blob_t *blob = OT::Sanitizer<OT::name>::sanitize (hb_face_reference_table (
font->face, HB_TAG ('n','a','m','e'))); |
71 const name *name_table = Sanitizer<name>::lock_instance (blob); | 123 const OT::name *name_table = OT::Sanitizer<OT::name>::lock_instance (blob); |
72 unsigned int len = name_table->get_name (3, 1, 0x409, 4, | 124 unsigned int len = name_table->get_name (3, 1, 0x409, 4, |
73 lf->lfFaceName, | 125 lf->lfFaceName, |
74 sizeof (lf->lfFaceName[0]) * LF_FACES
IZE) | 126 sizeof (lf->lfFaceName[0]) * LF_FACES
IZE) |
75 / sizeof (lf->lfFaceName[0]); | 127 / sizeof (lf->lfFaceName[0]); |
76 hb_blob_destroy (blob); | 128 hb_blob_destroy (blob); |
77 | 129 |
78 if (unlikely (!len)) { | 130 if (unlikely (!len)) { |
79 DEBUG_MSG (UNISCRIBE, NULL, "Didn't find English name table entry"); | 131 DEBUG_MSG (UNISCRIBE, NULL, "Didn't find English name table entry"); |
80 return false; | 132 return false; |
81 } | 133 } |
82 if (unlikely (len >= LF_FACESIZE)) { | 134 if (unlikely (len >= LF_FACESIZE)) { |
83 DEBUG_MSG (UNISCRIBE, NULL, "Font name too long"); | 135 DEBUG_MSG (UNISCRIBE, NULL, "Font name too long"); |
84 return false; | 136 return false; |
85 } | 137 } |
86 | 138 |
87 for (unsigned int i = 0; i < len; i++) | 139 for (unsigned int i = 0; i < len; i++) |
88 lf->lfFaceName[i] = hb_be_uint16 (lf->lfFaceName[i]); | 140 lf->lfFaceName[i] = hb_be_uint16 (lf->lfFaceName[i]); |
89 lf->lfFaceName[len] = 0; | 141 lf->lfFaceName[len] = 0; |
90 | 142 |
91 return true; | 143 return true; |
92 } | 144 } |
93 | 145 |
| 146 hb_uniscribe_shaper_font_data_t * |
| 147 _hb_uniscribe_shaper_font_data_create (hb_font_t *font) |
| 148 { |
| 149 if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return NULL
; |
94 | 150 |
95 static hb_user_data_key_t hb_uniscribe_data_key; | 151 hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) ca
lloc (1, sizeof (hb_uniscribe_shaper_font_data_t)); |
| 152 if (unlikely (!data)) |
| 153 return NULL; |
96 | 154 |
| 155 data->hdc = GetDC (NULL); |
97 | 156 |
98 static struct hb_uniscribe_face_data_t { | 157 if (unlikely (!populate_log_font (&data->log_font, font))) { |
99 HANDLE fh; | 158 DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed"); |
100 } _hb_uniscribe_face_data_nil = {0}; | 159 _hb_uniscribe_shaper_font_data_destroy (data); |
| 160 return NULL; |
| 161 } |
101 | 162 |
102 static void | 163 data->hfont = CreateFontIndirectW (&data->log_font); |
103 _hb_uniscribe_face_data_destroy (hb_uniscribe_face_data_t *data) | 164 if (unlikely (!data->hfont)) { |
104 { | 165 DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed"); |
105 if (data->fh) | 166 _hb_uniscribe_shaper_font_data_destroy (data); |
106 RemoveFontMemResourceEx (data->fh); | 167 return NULL; |
107 free (data); | 168 } |
108 } | |
109 | 169 |
110 static hb_uniscribe_face_data_t * | 170 if (!SelectObject (data->hdc, data->hfont)) { |
111 _hb_uniscribe_face_get_data (hb_face_t *face) | 171 DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed"); |
112 { | 172 _hb_uniscribe_shaper_font_data_destroy (data); |
113 hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) hb_face_get_user
_data (face, &hb_uniscribe_data_key); | 173 return NULL; |
114 if (likely (data)) return data; | |
115 | |
116 data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_
t)); | |
117 if (unlikely (!data)) | |
118 return &_hb_uniscribe_face_data_nil; | |
119 | |
120 | |
121 hb_blob_t *blob = hb_face_reference_blob (face); | |
122 unsigned int blob_length; | |
123 const char *blob_data = hb_blob_get_data (blob, &blob_length); | |
124 if (unlikely (!blob_length)) | |
125 DEBUG_MSG (UNISCRIBE, face, "Face has empty blob"); | |
126 | |
127 DWORD num_fonts_installed; | |
128 data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_font
s_installed); | |
129 hb_blob_destroy (blob); | |
130 if (unlikely (!data->fh)) | |
131 DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed"); | |
132 | |
133 | |
134 if (unlikely (!hb_face_set_user_data (face, &hb_uniscribe_data_key, data, | |
135 » » » » » (hb_destroy_func_t) _hb_uniscribe_face_d
ata_destroy, | |
136 » » » » » false))) | |
137 { | |
138 _hb_uniscribe_face_data_destroy (data); | |
139 data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &hb_uniscri
be_data_key); | |
140 if (data) | |
141 return data; | |
142 else | |
143 return &_hb_uniscribe_face_data_nil; | |
144 } | 174 } |
145 | 175 |
146 return data; | 176 return data; |
147 } | 177 } |
148 | 178 |
149 | 179 void |
150 static struct hb_uniscribe_font_data_t { | 180 _hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data) |
151 HDC hdc; | |
152 LOGFONTW log_font; | |
153 HFONT hfont; | |
154 SCRIPT_CACHE script_cache; | |
155 } _hb_uniscribe_font_data_nil = {NULL, NULL, NULL}; | |
156 | |
157 static void | |
158 _hb_uniscribe_font_data_destroy (hb_uniscribe_font_data_t *data) | |
159 { | 181 { |
160 if (data->hdc) | 182 if (data->hdc) |
161 ReleaseDC (NULL, data->hdc); | 183 ReleaseDC (NULL, data->hdc); |
162 if (data->hfont) | 184 if (data->hfont) |
163 DeleteObject (data->hfont); | 185 DeleteObject (data->hfont); |
164 if (data->script_cache) | 186 if (data->script_cache) |
165 ScriptFreeCache (&data->script_cache); | 187 ScriptFreeCache (&data->script_cache); |
166 free (data); | 188 free (data); |
167 } | 189 } |
168 | 190 |
169 static hb_uniscribe_font_data_t * | 191 |
170 _hb_uniscribe_font_get_data (hb_font_t *font) | 192 /* |
| 193 * shaper shape_plan data |
| 194 */ |
| 195 |
| 196 struct hb_uniscribe_shaper_shape_plan_data_t {}; |
| 197 |
| 198 hb_uniscribe_shaper_shape_plan_data_t * |
| 199 _hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_U
NUSED, |
| 200 » » » » » const hb_feature_t *user_features H
B_UNUSED, |
| 201 » » » » » unsigned int num_user_featur
es HB_UNUSED) |
171 { | 202 { |
172 hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) hb_font_get_user
_data (font, &hb_uniscribe_data_key); | 203 return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; |
173 if (likely (data)) return data; | 204 } |
174 | 205 |
175 data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_
t)); | 206 void |
176 if (unlikely (!data)) | 207 _hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_dat
a_t *data HB_UNUSED) |
177 return &_hb_uniscribe_font_data_nil; | 208 { |
| 209 } |
178 | 210 |
179 data->hdc = GetDC (NULL); | |
180 | 211 |
181 if (unlikely (!populate_log_font (&data->log_font, data->hdc, font))) | 212 /* |
182 DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed"); | 213 * shaper |
183 else { | 214 */ |
184 data->hfont = CreateFontIndirectW (&data->log_font); | |
185 if (unlikely (!data->hfont)) | |
186 DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed"); | |
187 if (!SelectObject (data->hdc, data->hfont)) | |
188 DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed"); | |
189 } | |
190 | |
191 if (unlikely (!hb_font_set_user_data (font, &hb_uniscribe_data_key, data, | |
192 » » » » » (hb_destroy_func_t) _hb_uniscribe_font_d
ata_destroy, | |
193 » » » » » false))) | |
194 { | |
195 _hb_uniscribe_font_data_destroy (data); | |
196 data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &hb_uniscri
be_data_key); | |
197 if (data) | |
198 return data; | |
199 else | |
200 return &_hb_uniscribe_font_data_nil; | |
201 } | |
202 | |
203 return data; | |
204 } | |
205 | 215 |
206 LOGFONTW * | 216 LOGFONTW * |
207 hb_uniscribe_font_get_logfontw (hb_font_t *font) | 217 hb_uniscribe_font_get_logfontw (hb_font_t *font) |
208 { | 218 { |
209 hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font); | 219 if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL; |
210 if (unlikely (!font_data)) | |
211 return NULL; | 220 return NULL; |
| 221 hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); |
212 return &font_data->log_font; | 222 return &font_data->log_font; |
213 } | 223 } |
214 | 224 |
215 HFONT | 225 HFONT |
216 hb_uniscribe_font_get_hfont (hb_font_t *font) | 226 hb_uniscribe_font_get_hfont (hb_font_t *font) |
217 { | 227 { |
218 hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font); | 228 if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL; |
219 if (unlikely (!font_data)) | 229 hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); |
220 return 0; | |
221 return font_data->hfont; | 230 return font_data->hfont; |
222 } | 231 } |
223 | 232 |
224 | 233 |
225 hb_bool_t | 234 hb_bool_t |
226 _hb_uniscribe_shape (hb_font_t *font, | 235 _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, |
| 236 » » hb_font_t *font, |
227 hb_buffer_t *buffer, | 237 hb_buffer_t *buffer, |
228 const hb_feature_t *features, | 238 const hb_feature_t *features, |
229 unsigned int num_features) | 239 unsigned int num_features) |
230 { | 240 { |
231 buffer->guess_properties (); | 241 hb_face_t *face = font->face; |
| 242 hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); |
| 243 hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); |
232 | 244 |
233 #define FAIL(...) \ | 245 #define FAIL(...) \ |
234 HB_STMT_START { \ | 246 HB_STMT_START { \ |
235 DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \ | 247 DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \ |
236 return false; \ | 248 return false; \ |
237 } HB_STMT_END; | 249 } HB_STMT_END; |
238 | 250 |
239 hb_uniscribe_face_data_t *face_data = _hb_uniscribe_face_get_data (font->face)
; | |
240 if (unlikely (!face_data->fh)) | |
241 FAIL ("Couldn't get face data"); | |
242 | |
243 hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font); | |
244 if (unlikely (!font_data->hfont)) | |
245 FAIL ("Couldn't get font font"); | |
246 | |
247 if (unlikely (!buffer->len)) | |
248 return true; | |
249 | |
250 HRESULT hr; | 251 HRESULT hr; |
251 | 252 |
252 retry: | 253 retry: |
253 | 254 |
254 unsigned int scratch_size; | 255 unsigned int scratch_size; |
255 char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); | 256 char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); |
256 | 257 |
257 /* Allocate char buffers; they all fit */ | 258 /* Allocate char buffers; they all fit */ |
258 | 259 |
259 #define ALLOCATE_ARRAY(Type, name, len) \ | 260 #define ALLOCATE_ARRAY(Type, name, len) \ |
260 Type *name = (Type *) scratch; \ | 261 Type *name = (Type *) scratch; \ |
261 scratch += len * sizeof (name[0]); \ | 262 scratch += (len) * sizeof ((name)[0]); \ |
262 scratch_size -= len * sizeof (name[0]); | 263 scratch_size -= (len) * sizeof ((name)[0]); |
263 | 264 |
264 #define utf16_index() var1.u32 | 265 #define utf16_index() var1.u32 |
265 | 266 |
266 WCHAR *pchars = (WCHAR *) scratch; | 267 WCHAR *pchars = (WCHAR *) scratch; |
267 unsigned int chars_len = 0; | 268 unsigned int chars_len = 0; |
268 for (unsigned int i = 0; i < buffer->len; i++) { | 269 for (unsigned int i = 0; i < buffer->len; i++) { |
269 hb_codepoint_t c = buffer->info[i].codepoint; | 270 hb_codepoint_t c = buffer->info[i].codepoint; |
270 buffer->info[i].utf16_index() = chars_len; | 271 buffer->info[i].utf16_index() = chars_len; |
271 if (likely (c < 0x10000)) | 272 if (likely (c < 0x10000)) |
272 pchars[chars_len++] = c; | 273 pchars[chars_len++] = c; |
(...skipping 15 matching lines...) Expand all Loading... |
288 sizeof (int) + | 289 sizeof (int) + |
289 sizeof (GOFFSET) + | 290 sizeof (GOFFSET) + |
290 sizeof (uint32_t)); | 291 sizeof (uint32_t)); |
291 | 292 |
292 ALLOCATE_ARRAY (WORD, glyphs, glyphs_size); | 293 ALLOCATE_ARRAY (WORD, glyphs, glyphs_size); |
293 ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size); | 294 ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size); |
294 ALLOCATE_ARRAY (int, advances, glyphs_size); | 295 ALLOCATE_ARRAY (int, advances, glyphs_size); |
295 ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size); | 296 ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size); |
296 ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size); | 297 ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size); |
297 | 298 |
| 299 #undef ALLOCATE_ARRAY |
298 | 300 |
299 #define MAX_ITEMS 10 | 301 #define MAX_ITEMS 256 |
300 | 302 |
301 SCRIPT_ITEM items[MAX_ITEMS + 1]; | 303 SCRIPT_ITEM items[MAX_ITEMS + 1]; |
302 SCRIPT_CONTROL bidi_control = {0}; | 304 SCRIPT_CONTROL bidi_control = {0}; |
303 SCRIPT_STATE bidi_state = {0}; | 305 SCRIPT_STATE bidi_state = {0}; |
304 WIN_ULONG script_tags[MAX_ITEMS]; | 306 ULONG script_tags[MAX_ITEMS]; |
305 int item_count; | 307 int item_count; |
306 | 308 |
307 /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */ | 309 /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */ |
308 //bidi_control.fMergeNeutralItems = true; | 310 //bidi_control.fMergeNeutralItems = true; |
309 *(uint32_t*)&bidi_control |= 1<<24; | 311 *(uint32_t*)&bidi_control |= 1<<24; |
310 | 312 |
311 bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0
: 1; | 313 bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0
: 1; |
312 // bidi_state.fOverrideDirection = 1; | 314 bidi_state.fOverrideDirection = 1; |
313 | 315 |
314 hr = ScriptItemizeOpenType (wchars, | 316 hr = ScriptItemizeOpenType (wchars, |
315 chars_len, | 317 chars_len, |
316 MAX_ITEMS, | 318 MAX_ITEMS, |
317 &bidi_control, | 319 &bidi_control, |
318 &bidi_state, | 320 &bidi_state, |
319 items, | 321 items, |
320 script_tags, | 322 script_tags, |
321 &item_count); | 323 &item_count); |
322 if (unlikely (FAILED (hr))) | 324 if (unlikely (FAILED (hr))) |
323 FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr); | 325 FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr); |
324 | 326 |
325 #undef MAX_ITEMS | 327 #undef MAX_ITEMS |
326 | 328 |
327 int *range_char_counts = NULL; | 329 int *range_char_counts = NULL; |
328 TEXTRANGE_PROPERTIES **range_properties = NULL; | 330 TEXTRANGE_PROPERTIES **range_properties = NULL; |
329 int range_count = 0; | 331 int range_count = 0; |
330 if (num_features) { | 332 if (num_features) { |
331 /* TODO setup ranges */ | 333 /* TODO setup ranges */ |
332 } | 334 } |
333 | 335 |
334 OPENTYPE_TAG language_tag = hb_ot_tag_from_language (buffer->props.language); | 336 OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->p
rops.language)); |
335 | 337 |
336 unsigned int glyphs_offset = 0; | 338 unsigned int glyphs_offset = 0; |
337 unsigned int glyphs_len; | 339 unsigned int glyphs_len; |
338 for (unsigned int i = 0; i < item_count; i++) | 340 bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); |
| 341 for (unsigned int j = 0; j < item_count; j++) |
339 { | 342 { |
340 unsigned int chars_offset = items[i].iCharPos; | 343 unsigned int i = backward ? item_count - 1 - j : j; |
341 unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset; | 344 unsigned int chars_offset = items[i].iCharPos; |
342 OPENTYPE_TAG script_tag = script_tags[i]; /* XXX buffer->props.script */ | 345 unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset; |
343 | 346 |
344 hr = ScriptShapeOpenType (font_data->hdc, | 347 retry_shape: |
345 » » » » &font_data->script_cache, | 348 hr = ScriptShapeOpenType (font_data->hdc, |
346 » » » » &items[i].a, | 349 » » » &font_data->script_cache, |
347 » » » » script_tag, | 350 » » » &items[i].a, |
348 » » » » language_tag, | 351 » » » script_tags[i], |
349 » » » » range_char_counts, | 352 » » » language_tag, |
350 » » » » range_properties, | 353 » » » range_char_counts, |
351 » » » » range_count, | 354 » » » range_properties, |
352 » » » » wchars + chars_offset, | 355 » » » range_count, |
353 » » » » item_chars_len, | 356 » » » wchars + chars_offset, |
354 » » » » glyphs_size - glyphs_offset, | 357 » » » item_chars_len, |
355 » » » » /* out */ | 358 » » » glyphs_size - glyphs_offset, |
356 » » » » log_clusters + chars_offset, | 359 » » » /* out */ |
357 » » » » char_props + chars_offset, | 360 » » » log_clusters + chars_offset, |
358 » » » » glyphs + glyphs_offset, | 361 » » » char_props + chars_offset, |
359 » » » » glyph_props + glyphs_offset, | 362 » » » glyphs + glyphs_offset, |
360 » » » » (int *) &glyphs_len); | 363 » » » glyph_props + glyphs_offset, |
| 364 » » » (int *) &glyphs_len); |
361 | 365 |
362 for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++
) | 366 if (unlikely (items[i].a.fNoGlyphIndex)) |
363 log_clusters[j] += glyphs_offset; | 367 FAIL ("ScriptShapeOpenType() set fNoGlyphIndex"); |
| 368 if (unlikely (hr == E_OUTOFMEMORY)) |
| 369 { |
| 370 buffer->ensure (buffer->allocated * 2); |
| 371 if (buffer->in_error) |
| 372 » FAIL ("Buffer resize failed"); |
| 373 goto retry; |
| 374 } |
| 375 if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT)) |
| 376 { |
| 377 if (items[i].a.eScript == SCRIPT_UNDEFINED) |
| 378 » FAIL ("ScriptShapeOpenType() failed: Font doesn't support script"); |
| 379 items[i].a.eScript = SCRIPT_UNDEFINED; |
| 380 goto retry_shape; |
| 381 } |
| 382 if (unlikely (FAILED (hr))) |
| 383 { |
| 384 FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr); |
| 385 } |
364 | 386 |
365 if (unlikely (items[i].a.fNoGlyphIndex)) | 387 for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++) |
366 » FAIL ("ScriptShapeOpenType() set fNoGlyphIndex"); | 388 log_clusters[j] += glyphs_offset; |
367 if (unlikely (hr == E_OUTOFMEMORY)) | |
368 { | |
369 buffer->ensure (buffer->allocated * 2); | |
370 » if (buffer->in_error) | |
371 » FAIL ("Buffer resize failed"); | |
372 » goto retry; | |
373 } | |
374 if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT)) | |
375 » FAIL ("ScriptShapeOpenType() failed: Font doesn't support script"); | |
376 if (unlikely (FAILED (hr))) | |
377 » FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr); | |
378 | 389 |
379 hr = ScriptPlaceOpenType (font_data->hdc, | 390 hr = ScriptPlaceOpenType (font_data->hdc, |
380 » » » » &font_data->script_cache, | 391 » » » &font_data->script_cache, |
381 » » » » &items[i].a, | 392 » » » &items[i].a, |
382 » » » » script_tag, | 393 » » » script_tags[i], |
383 » » » » language_tag, | 394 » » » language_tag, |
384 » » » » range_char_counts, | 395 » » » range_char_counts, |
385 » » » » range_properties, | 396 » » » range_properties, |
386 » » » » range_count, | 397 » » » range_count, |
387 » » » » wchars + chars_offset, | 398 » » » wchars + chars_offset, |
388 » » » » log_clusters + chars_offset, | 399 » » » log_clusters + chars_offset, |
389 » » » » char_props + chars_offset, | 400 » » » char_props + chars_offset, |
390 » » » » item_chars_len, | 401 » » » item_chars_len, |
391 » » » » glyphs + glyphs_offset, | 402 » » » glyphs + glyphs_offset, |
392 » » » » glyph_props + glyphs_offset, | 403 » » » glyph_props + glyphs_offset, |
393 » » » » glyphs_len, | 404 » » » glyphs_len, |
394 » » » » /* out */ | 405 » » » /* out */ |
395 » » » » advances + glyphs_offset, | 406 » » » advances + glyphs_offset, |
396 » » » » offsets + glyphs_offset, | 407 » » » offsets + glyphs_offset, |
397 » » » » NULL); | 408 » » » NULL); |
398 if (unlikely (FAILED (hr))) | 409 if (unlikely (FAILED (hr))) |
399 » FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr); | 410 FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr); |
400 | 411 |
401 glyphs_offset += glyphs_len; | 412 glyphs_offset += glyphs_len; |
402 } | 413 } |
403 glyphs_len = glyphs_offset; | 414 glyphs_len = glyphs_offset; |
404 | 415 |
405 /* Ok, we've got everything we need, now compose output buffer, | 416 /* Ok, we've got everything we need, now compose output buffer, |
406 * very, *very*, carefully! */ | 417 * very, *very*, carefully! */ |
407 | 418 |
408 /* Calculate visual-clusters. That's what we ship. */ | 419 /* Calculate visual-clusters. That's what we ship. */ |
409 for (unsigned int i = 0; i < glyphs_len; i++) | 420 for (unsigned int i = 0; i < glyphs_len; i++) |
410 vis_clusters[i] = -1; | 421 vis_clusters[i] = -1; |
411 for (unsigned int i = 0; i < buffer->len; i++) { | 422 for (unsigned int i = 0; i < buffer->len; i++) { |
412 uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]]; | 423 uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]]; |
413 *p = MIN (*p, buffer->info[i].cluster); | 424 *p = MIN (*p, buffer->info[i].cluster); |
414 } | 425 } |
415 if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) { | 426 if (!backward) { |
416 for (unsigned int i = 1; i < glyphs_len; i++) | 427 for (unsigned int i = 1; i < glyphs_len; i++) |
417 if (!glyph_props[i].sva.fClusterStart) | 428 if (vis_clusters[i] == -1) |
418 vis_clusters[i] = vis_clusters[i - 1]; | 429 vis_clusters[i] = vis_clusters[i - 1]; |
419 } else { | 430 } else { |
420 for (int i = glyphs_len - 2; i >= 0; i--) | 431 for (int i = glyphs_len - 2; i >= 0; i--) |
421 if (!glyph_props[i].sva.fClusterStart) | 432 if (vis_clusters[i] == -1) |
422 vis_clusters[i] = vis_clusters[i + 1]; | 433 vis_clusters[i] = vis_clusters[i + 1]; |
423 } | 434 } |
424 | 435 |
425 #undef utf16_index | 436 #undef utf16_index |
426 | 437 |
427 buffer->ensure (glyphs_len); | 438 buffer->ensure (glyphs_len); |
428 if (buffer->in_error) | 439 if (buffer->in_error) |
429 FAIL ("Buffer in error"); | 440 FAIL ("Buffer in error"); |
430 | 441 |
431 #undef FAIL | 442 #undef FAIL |
(...skipping 24 matching lines...) Expand all Loading... |
456 pos->x_advance = info->mask; | 467 pos->x_advance = info->mask; |
457 pos->x_offset = info->var1.u32; | 468 pos->x_offset = info->var1.u32; |
458 pos->y_offset = info->var2.u32; | 469 pos->y_offset = info->var2.u32; |
459 } | 470 } |
460 | 471 |
461 /* Wow, done! */ | 472 /* Wow, done! */ |
462 return true; | 473 return true; |
463 } | 474 } |
464 | 475 |
465 | 476 |
OLD | NEW |