Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: third_party/harfbuzz-ng/src/hb-buffer.cc

Issue 9223010: Update harfbuzz-ng to 1a5a91dc0d8bf4b72a2f22dc6300b06ad7000b79. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Don't use -M option for 'git diff' to patch correctly Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1998-2004 David Turner and Werner Lemberg 2 * Copyright © 1998-2004 David Turner and Werner Lemberg
3 * Copyright (C) 2004,2007,2009,2010 Red Hat, Inc. 3 * Copyright © 2004,2007,2009,2010 Red Hat, Inc.
4 * Copyright © 2011 Google, Inc.
4 * 5 *
5 * This is part of HarfBuzz, a text shaping library. 6 * This is part of HarfBuzz, a text shaping library.
6 * 7 *
7 * Permission is hereby granted, without written agreement and without 8 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this 9 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the 10 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in 11 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software. 12 * all copies of this software.
12 * 13 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE. 18 * DAMAGE.
18 * 19 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 * 25 *
25 * Red Hat Author(s): Owen Taylor, Behdad Esfahbod 26 * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
27 * Google Author(s): Behdad Esfahbod
26 */ 28 */
27 29
28 #include "hb-buffer-private.hh" 30 #include "hb-buffer-private.hh"
29 31
30 #include <string.h> 32 #include <string.h>
31 33
32 HB_BEGIN_DECLS 34
35
36 #ifndef HB_DEBUG_BUFFER
37 #define HB_DEBUG_BUFFER (HB_DEBUG+0)
38 #endif
33 39
34 40
35 static hb_buffer_t _hb_buffer_nil = { 41 static hb_buffer_t _hb_buffer_nil = {
36 HB_REFERENCE_COUNT_INVALID, /* ref_count */ 42 HB_OBJECT_HEADER_STATIC,
37 43
38 &_hb_unicode_funcs_nil /* unicode */ 44 &_hb_unicode_funcs_default,
45 {
46 HB_DIRECTION_INVALID,
47 HB_SCRIPT_INVALID,
48 NULL,
49 },
50
51 TRUE, /* in_error */
52 TRUE, /* have_output */
53 TRUE /* have_positions */
39 }; 54 };
40 55
41 /* Here is how the buffer works internally: 56 /* Here is how the buffer works internally:
42 * 57 *
43 * There are two info pointers: info and out_info. They always have 58 * There are two info pointers: info and out_info. They always have
44 * the same allocated size, but different lengths. 59 * the same allocated size, but different lengths.
45 * 60 *
46 * As an optimization, both info and out_info may point to the 61 * As an optimization, both info and out_info may point to the
47 * same piece of memory, which is owned by info. This remains the 62 * same piece of memory, which is owned by info. This remains the
48 * case as long as out_len doesn't exceed len at any time. 63 * case as long as out_len doesn't exceed i at any time.
49 * In that case, swap() is no-op and the glyph operations operate 64 * In that case, swap_buffers() is no-op and the glyph operations operate
50 * mostly in-place. 65 * mostly in-place.
51 * 66 *
52 * As soon as out_info gets longer than info, out_info is moved over 67 * As soon as out_info gets longer than info, out_info is moved over
53 * to an alternate buffer (which we reuse the pos buffer for!), and its 68 * to an alternate buffer (which we reuse the pos buffer for!), and its
54 * current contents (out_len entries) are copied to the new place. 69 * current contents (out_len entries) are copied to the new place.
55 * This should all remain transparent to the user. swap() then 70 * This should all remain transparent to the user. swap_buffers() then
56 * switches info and out_info. 71 * switches info and out_info.
57 */ 72 */
58 73
59 74
60 static hb_bool_t 75
61 _hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size) 76 /* Internal API */
62 { 77
63 if (unlikely (buffer->in_error)) 78 bool
79 hb_buffer_t::enlarge (unsigned int size)
80 {
81 if (unlikely (in_error))
64 return FALSE; 82 return FALSE;
65 83
66 unsigned int new_allocated = buffer->allocated; 84 unsigned int new_allocated = allocated;
67 hb_glyph_position_t *new_pos; 85 hb_glyph_position_t *new_pos = NULL;
68 hb_glyph_info_t *new_info; 86 hb_glyph_info_t *new_info = NULL;
69 bool separate_out; 87 bool separate_out = out_info != info;
70 88
71 separate_out = buffer->out_info != buffer->info; 89 if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
90 goto done;
72 91
73 while (size > new_allocated) 92 while (size > new_allocated)
74 new_allocated += (new_allocated >> 1) + 8; 93 new_allocated += (new_allocated >> 1) + 32;
75 94
76 new_pos = (hb_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0])); 95 ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
77 new_info = (hb_glyph_info_t *) realloc (buffer->info, new_allocated * sizeof ( buffer->info[0])); 96 if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0])) ))
78 97 goto done;
98
99 new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0] ));
100 new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]) );
101
102 done:
79 if (unlikely (!new_pos || !new_info)) 103 if (unlikely (!new_pos || !new_info))
80 buffer->in_error = TRUE; 104 in_error = TRUE;
81 105
82 if (likely (new_pos)) 106 if (likely (new_pos))
83 buffer->pos = new_pos; 107 pos = new_pos;
84 108
85 if (likely (new_info)) 109 if (likely (new_info))
86 buffer->info = new_info; 110 info = new_info;
87 111
88 buffer->out_info = separate_out ? (hb_glyph_info_t *) buffer->pos : buffer->in fo; 112 out_info = separate_out ? (hb_glyph_info_t *) pos : info;
89 if (likely (!buffer->in_error)) 113 if (likely (!in_error))
90 buffer->allocated = new_allocated; 114 allocated = new_allocated;
91 115
92 return likely (!buffer->in_error); 116 return likely (!in_error);
93 } 117 }
94 118
95 static inline hb_bool_t 119 bool
96 _hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size) 120 hb_buffer_t::make_room_for (unsigned int num_in,
97 { 121 » » » unsigned int num_out)
98 return likely (size <= buffer->allocated) ? TRUE : _hb_buffer_enlarge (buffer, size); 122 {
99 } 123 if (unlikely (!ensure (out_len + num_out))) return FALSE;
100 124
101 static inline hb_bool_t 125 if (out_info == info &&
102 _hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size) 126 out_len + num_out > idx + num_in)
103 {
104 if (unlikely (!_hb_buffer_ensure (buffer, size))) return FALSE;
105
106 if (buffer->out_info == buffer->info)
107 { 127 {
108 assert (buffer->have_output); 128 assert (have_output);
109 129
110 buffer->out_info = (hb_glyph_info_t *) buffer->pos; 130 out_info = (hb_glyph_info_t *) pos;
111 memcpy (buffer->out_info, buffer->info, buffer->out_len * sizeof (buffer->ou t_info[0])); 131 memcpy (out_info, info, out_len * sizeof (out_info[0]));
112 } 132 }
113 133
114 return TRUE; 134 return TRUE;
115 } 135 }
116 136
117 137 void *
118 /* Public API */ 138 hb_buffer_t::get_scratch_buffer (unsigned int *size)
119 139 {
120 hb_buffer_t * 140 have_output = FALSE;
121 hb_buffer_create (unsigned int pre_alloc_size) 141 have_positions = FALSE;
122 { 142 out_len = 0;
123 hb_buffer_t *buffer; 143 *size = allocated * sizeof (pos[0]);
124 144 return pos;
125 if (!HB_OBJECT_DO_CREATE (hb_buffer_t, buffer)) 145 }
126 return &_hb_buffer_nil; 146
127 147
128 if (pre_alloc_size) 148 /* HarfBuzz-Internal API */
129 _hb_buffer_ensure (buffer, pre_alloc_size); 149
130 150 void
131 buffer->unicode = &_hb_unicode_funcs_nil; 151 hb_buffer_t::reset (void)
132 152 {
133 return buffer; 153 if (unlikely (hb_object_is_inert (this)))
134 } 154 return;
135 155
136 hb_buffer_t * 156 hb_unicode_funcs_destroy (unicode);
137 hb_buffer_reference (hb_buffer_t *buffer) 157 unicode = _hb_buffer_nil.unicode;
138 { 158
139 HB_OBJECT_DO_REFERENCE (buffer); 159 props = _hb_buffer_nil.props;
140 } 160
141 161 in_error = FALSE;
142 unsigned int 162 have_output = FALSE;
143 hb_buffer_get_reference_count (hb_buffer_t *buffer) 163 have_positions = FALSE;
144 { 164
145 HB_OBJECT_DO_GET_REFERENCE_COUNT (buffer); 165 idx = 0;
146 } 166 len = 0;
147 167 out_len = 0;
148 void 168
149 hb_buffer_destroy (hb_buffer_t *buffer) 169 serial = 0;
150 { 170 memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
151 HB_OBJECT_DO_DESTROY (buffer); 171 memset (allocated_var_owner, 0, sizeof allocated_var_owner);
152 172
153 hb_unicode_funcs_destroy (buffer->unicode); 173 out_info = info;
154 174 }
155 free (buffer->info); 175
156 free (buffer->pos); 176 void
157 177 hb_buffer_t::add (hb_codepoint_t codepoint,
158 free (buffer); 178 » » hb_mask_t mask,
159 } 179 » » unsigned int cluster)
160
161
162 void
163 hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
164 » » » hb_unicode_funcs_t *unicode)
165 {
166 if (!unicode)
167 unicode = &_hb_unicode_funcs_nil;
168
169 hb_unicode_funcs_reference (unicode);
170 hb_unicode_funcs_destroy (buffer->unicode);
171 buffer->unicode = unicode;
172 }
173
174 hb_unicode_funcs_t *
175 hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
176 {
177 return buffer->unicode;
178 }
179
180 void
181 hb_buffer_set_direction (hb_buffer_t *buffer,
182 » » » hb_direction_t direction)
183
184 {
185 buffer->props.direction = direction;
186 }
187
188 hb_direction_t
189 hb_buffer_get_direction (hb_buffer_t *buffer)
190 {
191 return buffer->props.direction;
192 }
193
194 void
195 hb_buffer_set_script (hb_buffer_t *buffer,
196 » » hb_script_t script)
197 {
198 buffer->props.script = script;
199 }
200
201 hb_script_t
202 hb_buffer_get_script (hb_buffer_t *buffer)
203 {
204 return buffer->props.script;
205 }
206
207 void
208 hb_buffer_set_language (hb_buffer_t *buffer,
209 » » » hb_language_t language)
210 {
211 buffer->props.language = language;
212 }
213
214 hb_language_t
215 hb_buffer_get_language (hb_buffer_t *buffer)
216 {
217 return buffer->props.language;
218 }
219
220
221 void
222 hb_buffer_clear (hb_buffer_t *buffer)
223 {
224 buffer->have_output = FALSE;
225 buffer->have_positions = FALSE;
226 buffer->in_error = FALSE;
227 buffer->len = 0;
228 buffer->out_len = 0;
229 buffer->i = 0;
230 buffer->out_info = buffer->info;
231 buffer->serial = 0;
232 }
233
234 hb_bool_t
235 hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
236 {
237 return _hb_buffer_ensure (buffer, size);
238 }
239
240 void
241 hb_buffer_add_glyph (hb_buffer_t *buffer,
242 » » hb_codepoint_t codepoint,
243 » » hb_mask_t mask,
244 » » unsigned int cluster)
245 { 180 {
246 hb_glyph_info_t *glyph; 181 hb_glyph_info_t *glyph;
247 182
248 if (unlikely (!_hb_buffer_ensure (buffer, buffer->len + 1))) return; 183 if (unlikely (!ensure (len + 1))) return;
249 184
250 glyph = &buffer->info[buffer->len]; 185 glyph = &info[len];
251 186
252 memset (glyph, 0, sizeof (*glyph)); 187 memset (glyph, 0, sizeof (*glyph));
253 glyph->codepoint = codepoint; 188 glyph->codepoint = codepoint;
254 glyph->mask = mask; 189 glyph->mask = mask;
255 glyph->cluster = cluster; 190 glyph->cluster = cluster;
256 191
257 buffer->len++; 192 len++;
258 } 193 }
259 194
260 void 195 void
261 hb_buffer_clear_positions (hb_buffer_t *buffer) 196 hb_buffer_t::clear_output (void)
262 { 197 {
263 _hb_buffer_clear_output (buffer); 198 if (unlikely (hb_object_is_inert (this)))
264 buffer->have_output = FALSE; 199 return;
265 buffer->have_positions = TRUE; 200
266 201 have_output = TRUE;
267 if (unlikely (!buffer->pos)) 202 have_positions = FALSE;
268 { 203
269 buffer->pos = (hb_glyph_position_t *) calloc (buffer->allocated, sizeof (buf fer->pos[0])); 204 out_len = 0;
270 return; 205 out_info = info;
271 } 206 }
272 207
273 memset (buffer->pos, 0, sizeof (buffer->pos[0]) * buffer->len); 208 void
274 } 209 hb_buffer_t::clear_positions (void)
275 210 {
276 /* HarfBuzz-Internal API */ 211 if (unlikely (hb_object_is_inert (this)))
277 212 return;
278 void 213
279 _hb_buffer_clear_output (hb_buffer_t *buffer) 214 have_output = FALSE;
280 { 215 have_positions = TRUE;
281 buffer->have_output = TRUE; 216
282 buffer->have_positions = FALSE; 217 memset (pos, 0, sizeof (pos[0]) * len);
283 buffer->out_len = 0; 218 }
284 buffer->out_info = buffer->info; 219
285 } 220 void
286 221 hb_buffer_t::swap_buffers (void)
287 void 222 {
288 _hb_buffer_swap (hb_buffer_t *buffer) 223 if (unlikely (in_error)) return;
289 { 224
290 unsigned int tmp; 225 assert (have_output);
291 226
292 assert (buffer->have_output); 227 if (out_info != info)
293
294 if (unlikely (buffer->in_error)) return;
295
296 if (buffer->out_info != buffer->info)
297 { 228 {
298 hb_glyph_info_t *tmp_string; 229 hb_glyph_info_t *tmp_string;
299 tmp_string = buffer->info; 230 tmp_string = info;
300 buffer->info = buffer->out_info; 231 info = out_info;
301 buffer->out_info = tmp_string; 232 out_info = tmp_string;
302 buffer->pos = (hb_glyph_position_t *) buffer->out_info; 233 pos = (hb_glyph_position_t *) out_info;
303 } 234 }
304 235
305 tmp = buffer->len; 236 unsigned int tmp;
306 buffer->len = buffer->out_len; 237 tmp = len;
307 buffer->out_len = tmp; 238 len = out_len;
308 239 out_len = tmp;
309 buffer->i = 0; 240
310 } 241 idx = 0;
311 242 }
312 void 243
313 _hb_buffer_replace_glyphs_be16 (hb_buffer_t *buffer, 244 void
314 » » » » unsigned int num_in, 245 hb_buffer_t::replace_glyphs_be16 (unsigned int num_in,
315 » » » » unsigned int num_out, 246 » » » » unsigned int num_out,
316 » » » » const uint16_t *glyph_data_be) 247 » » » » const uint16_t *glyph_data_be)
317 { 248 {
318 if (buffer->out_info != buffer->info || 249 if (!make_room_for (num_in, num_out)) return;
319 buffer->out_len + num_out > buffer->i + num_in) 250
251 hb_glyph_info_t orig_info = info[idx];
252 for (unsigned int i = 1; i < num_in; i++)
320 { 253 {
321 if (unlikely (!_hb_buffer_ensure_separate (buffer, buffer->out_len + num_out ))) 254 hb_glyph_info_t *inf = &info[idx + i];
322 return; 255 orig_info.cluster = MIN (orig_info.cluster, inf->cluster);
323 } 256 }
324 257
325 hb_glyph_info_t orig_info = buffer->info[buffer->i]; 258 hb_glyph_info_t *pinfo = &out_info[out_len];
326
327 for (unsigned int i = 0; i < num_out; i++) 259 for (unsigned int i = 0; i < num_out; i++)
328 { 260 {
329 hb_glyph_info_t *info = &buffer->out_info[buffer->out_len + i]; 261 *pinfo = orig_info;
330 *info = orig_info; 262 pinfo->codepoint = hb_be_uint16 (glyph_data_be[i]);
331 info->codepoint = hb_be_uint16 (glyph_data_be[i]); 263 pinfo++;
332 } 264 }
333 265
334 buffer->i += num_in; 266 idx += num_in;
335 buffer->out_len += num_out; 267 out_len += num_out;
336 } 268 }
337 269
338 void 270 void
339 _hb_buffer_replace_glyph (hb_buffer_t *buffer, 271 hb_buffer_t::replace_glyphs (unsigned int num_in,
340 » » » hb_codepoint_t glyph_index) 272 » » » unsigned int num_out,
341 { 273 » » » const uint16_t *glyph_data)
342 hb_glyph_info_t *info; 274 {
343 275 if (!make_room_for (num_in, num_out)) return;
344 if (buffer->out_info != buffer->info) 276
277 hb_glyph_info_t orig_info = info[idx];
278 for (unsigned int i = 1; i < num_in; i++)
345 { 279 {
346 if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return; 280 hb_glyph_info_t *inf = &info[idx + i];
347 buffer->out_info[buffer->out_len] = buffer->info[buffer->i]; 281 orig_info.cluster = MIN (orig_info.cluster, inf->cluster);
348 } 282 }
349 else if (buffer->out_len != buffer->i) 283
350 buffer->out_info[buffer->out_len] = buffer->info[buffer->i]; 284 hb_glyph_info_t *pinfo = &out_info[out_len];
351 285 for (unsigned int i = 0; i < num_out; i++)
352 info = &buffer->out_info[buffer->out_len];
353 info->codepoint = glyph_index;
354
355 buffer->i++;
356 buffer->out_len++;
357 }
358
359 void
360 _hb_buffer_next_glyph (hb_buffer_t *buffer)
361 {
362 if (buffer->have_output)
363 { 286 {
364 if (buffer->out_info != buffer->info) 287 *pinfo = orig_info;
288 pinfo->codepoint = glyph_data[i];
289 pinfo++;
290 }
291
292 idx += num_in;
293 out_len += num_out;
294 }
295
296 void
297 hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
298 {
299 if (!make_room_for (0, 1)) return;
300
301 out_info[out_len] = info[idx];
302 out_info[out_len].codepoint = glyph_index;
303
304 out_len++;
305 }
306
307 void
308 hb_buffer_t::copy_glyph (void)
309 {
310 if (!make_room_for (0, 1)) return;
311
312 out_info[out_len] = info[idx];
313
314 out_len++;
315 }
316
317 void
318 hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
319 {
320 if (!make_room_for (1, 1)) return;
321
322 out_info[out_len] = info[idx];
323 out_info[out_len].codepoint = glyph_index;
324
325 idx++;
326 out_len++;
327 }
328
329 void
330 hb_buffer_t::next_glyph (void)
331 {
332 if (have_output)
333 {
334 if (out_info != info)
365 { 335 {
366 if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return; 336 if (unlikely (!ensure (out_len + 1))) return;
367 buffer->out_info[buffer->out_len] = buffer->info[buffer->i]; 337 out_info[out_len] = info[idx];
368 } 338 }
369 else if (buffer->out_len != buffer->i) 339 else if (out_len != idx)
370 buffer->out_info[buffer->out_len] = buffer->info[buffer->i]; 340 out_info[out_len] = info[idx];
371 341
372 buffer->out_len++; 342 out_len++;
373 } 343 }
374 344
375 buffer->i++; 345 idx++;
376 } 346 }
377 347
378 void 348 void
379 _hb_buffer_reset_masks (hb_buffer_t *buffer, 349 hb_buffer_t::set_masks (hb_mask_t value,
380 » » » hb_mask_t mask) 350 » » » hb_mask_t mask,
381 { 351 » » » unsigned int cluster_start,
382 unsigned int count = buffer->len; 352 » » » unsigned int cluster_end)
383 for (unsigned int i = 0; i < count; i++)
384 buffer->info[i].mask = mask;
385 }
386
387 void
388 _hb_buffer_add_masks (hb_buffer_t *buffer,
389 » » hb_mask_t mask)
390 {
391 unsigned int count = buffer->len;
392 for (unsigned int i = 0; i < count; i++)
393 buffer->info[i].mask |= mask;
394 }
395
396 void
397 _hb_buffer_set_masks (hb_buffer_t *buffer,
398 » » hb_mask_t value,
399 » » hb_mask_t mask,
400 » » unsigned int cluster_start,
401 » » unsigned int cluster_end)
402 { 353 {
403 hb_mask_t not_mask = ~mask; 354 hb_mask_t not_mask = ~mask;
404 value &= mask; 355 value &= mask;
405 356
406 if (!mask) 357 if (!mask)
407 return; 358 return;
408 359
409 if (cluster_start == 0 && cluster_end == (unsigned int)-1) { 360 if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
410 unsigned int count = buffer->len; 361 unsigned int count = len;
411 for (unsigned int i = 0; i < count; i++) 362 for (unsigned int i = 0; i < count; i++)
412 buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value; 363 info[i].mask = (info[i].mask & not_mask) | value;
413 return; 364 return;
414 } 365 }
415 366
416 /* XXX can't bsearch since .cluster may not be sorted. */ 367 unsigned int count = len;
417 /* Binary search to find the start position and go from there. */ 368 for (unsigned int i = 0; i < count; i++)
418 unsigned int min = 0, max = buffer->len; 369 if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
419 while (min < max) 370 info[i].mask = (info[i].mask & not_mask) | value;
420 { 371 }
421 unsigned int mid = min + ((max - min) / 2); 372
422 if (buffer->info[mid].cluster < cluster_start) 373 void
423 min = mid + 1; 374 hb_buffer_t::reverse_range (unsigned int start,
424 else 375 » » » unsigned int end)
425 max = mid; 376 {
426 } 377 unsigned int i, j;
427 unsigned int count = buffer->len; 378
428 for (unsigned int i = min; i < count && buffer->info[i].cluster < cluster_end; i++) 379 if (start == end - 1)
429 buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value; 380 return;
430 } 381
431 382 for (i = start, j = end - 1; i < j; i++, j--) {
432 383 hb_glyph_info_t t;
433 /* Public API again */ 384
385 t = info[i];
386 info[i] = info[j];
387 info[j] = t;
388 }
389
390 if (pos) {
391 for (i = start, j = end - 1; i < j; i++, j--) {
392 hb_glyph_position_t t;
393
394 t = pos[i];
395 pos[i] = pos[j];
396 pos[j] = t;
397 }
398 }
399 }
400
401 void
402 hb_buffer_t::reverse (void)
403 {
404 if (unlikely (!len))
405 return;
406
407 reverse_range (0, len);
408 }
409
410 void
411 hb_buffer_t::reverse_clusters (void)
412 {
413 unsigned int i, start, count, last_cluster;
414
415 if (unlikely (!len))
416 return;
417
418 reverse ();
419
420 count = len;
421 start = 0;
422 last_cluster = info[0].cluster;
423 for (i = 1; i < count; i++) {
424 if (last_cluster != info[i].cluster) {
425 reverse_range (start, i);
426 start = i;
427 last_cluster = info[i].cluster;
428 }
429 }
430 reverse_range (start, i);
431 }
432
433 void
434 hb_buffer_t::guess_properties (void)
435 {
436 /* If script is set to INVALID, guess from buffer contents */
437 if (props.script == HB_SCRIPT_INVALID) {
438 for (unsigned int i = 0; i < len; i++) {
439 hb_script_t script = hb_unicode_script (unicode, info[i].codepoint);
440 if (likely (script != HB_SCRIPT_COMMON &&
441 » » script != HB_SCRIPT_INHERITED &&
442 » » script != HB_SCRIPT_UNKNOWN)) {
443 props.script = script;
444 break;
445 }
446 }
447 }
448
449 /* If direction is set to INVALID, guess from script */
450 if (props.direction == HB_DIRECTION_INVALID) {
451 props.direction = hb_script_get_horizontal_direction (props.script);
452 }
453
454 /* If language is not set, use default language from locale */
455 if (props.language == HB_LANGUAGE_INVALID) {
456 /* TODO get_default_for_script? using $LANGUAGE */
457 props.language = hb_language_get_default ();
458 }
459 }
460
461
462 static inline void
463 dump_var_allocation (const hb_buffer_t *buffer)
464 {
465 char buf[80];
466 for (unsigned int i = 0; i < 8; i++)
467 buf[i] = '0' + buffer->allocated_var_bytes[7 - i];
468 buf[8] = '\0';
469 DEBUG_MSG (BUFFER, buffer,
470 » "Current var allocation: %s",
471 » buf);
472 }
473
474 void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const c har *owner)
475 {
476 assert (byte_i < 8 && byte_i + count <= 8);
477
478 if (DEBUG (BUFFER))
479 dump_var_allocation (this);
480 DEBUG_MSG (BUFFER, this,
481 » "Allocating var bytes %d..%d for %s",
482 » byte_i, byte_i + count - 1, owner);
483
484 for (unsigned int i = byte_i; i < byte_i + count; i++) {
485 assert (!allocated_var_bytes[i]);
486 allocated_var_bytes[i]++;
487 allocated_var_owner[i] = owner;
488 }
489 }
490
491 void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
492 {
493 if (DEBUG (BUFFER))
494 dump_var_allocation (this);
495
496 DEBUG_MSG (BUFFER, this,
497 » "Deallocating var bytes %d..%d for %s",
498 » byte_i, byte_i + count - 1, owner);
499
500 assert (byte_i < 8 && byte_i + count <= 8);
501 for (unsigned int i = byte_i; i < byte_i + count; i++) {
502 assert (allocated_var_bytes[i]);
503 assert (0 == strcmp (allocated_var_owner[i], owner));
504 allocated_var_bytes[i]--;
505 }
506 }
507
508 void hb_buffer_t::deallocate_var_all (void)
509 {
510 memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes));
511 memset (allocated_var_owner, 0, sizeof (allocated_var_owner));
512 }
513
514 /* Public API */
515
516 hb_buffer_t *
517 hb_buffer_create ()
518 {
519 hb_buffer_t *buffer;
520
521 if (!(buffer = hb_object_create<hb_buffer_t> ()))
522 return &_hb_buffer_nil;
523
524 buffer->reset ();
525
526 return buffer;
527 }
528
529 hb_buffer_t *
530 hb_buffer_get_empty (void)
531 {
532 return &_hb_buffer_nil;
533 }
534
535 hb_buffer_t *
536 hb_buffer_reference (hb_buffer_t *buffer)
537 {
538 return hb_object_reference (buffer);
539 }
540
541 void
542 hb_buffer_destroy (hb_buffer_t *buffer)
543 {
544 if (!hb_object_destroy (buffer)) return;
545
546 hb_unicode_funcs_destroy (buffer->unicode);
547
548 free (buffer->info);
549 free (buffer->pos);
550
551 free (buffer);
552 }
553
554 hb_bool_t
555 hb_buffer_set_user_data (hb_buffer_t *buffer,
556 » » » hb_user_data_key_t *key,
557 » » » void * data,
558 » » » hb_destroy_func_t destroy,
559 » » » hb_bool_t replace)
560 {
561 return hb_object_set_user_data (buffer, key, data, destroy, replace);
562 }
563
564 void *
565 hb_buffer_get_user_data (hb_buffer_t *buffer,
566 » » » hb_user_data_key_t *key)
567 {
568 return hb_object_get_user_data (buffer, key);
569 }
570
571
572 void
573 hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
574 » » » hb_unicode_funcs_t *unicode)
575 {
576 if (unlikely (hb_object_is_inert (buffer)))
577 return;
578
579 if (!unicode)
580 unicode = _hb_buffer_nil.unicode;
581
582 hb_unicode_funcs_reference (unicode);
583 hb_unicode_funcs_destroy (buffer->unicode);
584 buffer->unicode = unicode;
585 }
586
587 hb_unicode_funcs_t *
588 hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
589 {
590 return buffer->unicode;
591 }
592
593 void
594 hb_buffer_set_direction (hb_buffer_t *buffer,
595 » » » hb_direction_t direction)
596
597 {
598 if (unlikely (hb_object_is_inert (buffer)))
599 return;
600
601 buffer->props.direction = direction;
602 }
603
604 hb_direction_t
605 hb_buffer_get_direction (hb_buffer_t *buffer)
606 {
607 return buffer->props.direction;
608 }
609
610 void
611 hb_buffer_set_script (hb_buffer_t *buffer,
612 » » hb_script_t script)
613 {
614 if (unlikely (hb_object_is_inert (buffer)))
615 return;
616
617 buffer->props.script = script;
618 }
619
620 hb_script_t
621 hb_buffer_get_script (hb_buffer_t *buffer)
622 {
623 return buffer->props.script;
624 }
625
626 void
627 hb_buffer_set_language (hb_buffer_t *buffer,
628 » » » hb_language_t language)
629 {
630 if (unlikely (hb_object_is_inert (buffer)))
631 return;
632
633 buffer->props.language = language;
634 }
635
636 hb_language_t
637 hb_buffer_get_language (hb_buffer_t *buffer)
638 {
639 return buffer->props.language;
640 }
641
642
643 void
644 hb_buffer_reset (hb_buffer_t *buffer)
645 {
646 buffer->reset ();
647 }
648
649 hb_bool_t
650 hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
651 {
652 return buffer->ensure (size);
653 }
654
655 hb_bool_t
656 hb_buffer_allocation_successful (hb_buffer_t *buffer)
657 {
658 return !buffer->in_error;
659 }
660
661 void
662 hb_buffer_add (hb_buffer_t *buffer,
663 » hb_codepoint_t codepoint,
664 » hb_mask_t mask,
665 » unsigned int cluster)
666 {
667 buffer->add (codepoint, mask, cluster);
668 }
669
670 hb_bool_t
671 hb_buffer_set_length (hb_buffer_t *buffer,
672 » » unsigned int length)
673 {
674 if (!buffer->ensure (length))
675 return FALSE;
676
677 /* Wipe the new space */
678 if (length > buffer->len) {
679 memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
680 if (buffer->have_positions)
681 memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
682 }
683
684 buffer->len = length;
685 return TRUE;
686 }
434 687
435 unsigned int 688 unsigned int
436 hb_buffer_get_length (hb_buffer_t *buffer) 689 hb_buffer_get_length (hb_buffer_t *buffer)
437 { 690 {
438 return buffer->len; 691 return buffer->len;
439 } 692 }
440 693
441 /* Return value valid as long as buffer not modified */ 694 /* Return value valid as long as buffer not modified */
442 hb_glyph_info_t * 695 hb_glyph_info_t *
443 hb_buffer_get_glyph_infos (hb_buffer_t *buffer) 696 hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
697 unsigned int *length)
444 { 698 {
699 if (length)
700 *length = buffer->len;
701
445 return (hb_glyph_info_t *) buffer->info; 702 return (hb_glyph_info_t *) buffer->info;
446 } 703 }
447 704
448 /* Return value valid as long as buffer not modified */ 705 /* Return value valid as long as buffer not modified */
449 hb_glyph_position_t * 706 hb_glyph_position_t *
450 hb_buffer_get_glyph_positions (hb_buffer_t *buffer) 707 hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
708 unsigned int *length)
451 { 709 {
452 if (!buffer->have_positions) 710 if (!buffer->have_positions)
453 hb_buffer_clear_positions (buffer); 711 buffer->clear_positions ();
712
713 if (length)
714 *length = buffer->len;
454 715
455 return (hb_glyph_position_t *) buffer->pos; 716 return (hb_glyph_position_t *) buffer->pos;
456 } 717 }
457 718
458
459 static void
460 reverse_range (hb_buffer_t *buffer,
461 unsigned int start,
462 unsigned int end)
463 {
464 unsigned int i, j;
465
466 for (i = start, j = end - 1; i < j; i++, j--) {
467 hb_glyph_info_t t;
468
469 t = buffer->info[i];
470 buffer->info[i] = buffer->info[j];
471 buffer->info[j] = t;
472 }
473
474 if (buffer->pos) {
475 for (i = 0, j = end - 1; i < j; i++, j--) {
476 hb_glyph_position_t t;
477
478 t = buffer->pos[i];
479 buffer->pos[i] = buffer->pos[j];
480 buffer->pos[j] = t;
481 }
482 }
483 }
484
485 void 719 void
486 hb_buffer_reverse (hb_buffer_t *buffer) 720 hb_buffer_reverse (hb_buffer_t *buffer)
487 { 721 {
488 if (unlikely (!buffer->len)) 722 buffer->reverse ();
489 return;
490
491 reverse_range (buffer, 0, buffer->len);
492 } 723 }
493 724
494 void 725 void
495 hb_buffer_reverse_clusters (hb_buffer_t *buffer) 726 hb_buffer_reverse_clusters (hb_buffer_t *buffer)
496 { 727 {
497 unsigned int i, start, count, last_cluster; 728 buffer->reverse_clusters ();
498
499 if (unlikely (!buffer->len))
500 return;
501
502 hb_buffer_reverse (buffer);
503
504 count = buffer->len;
505 start = 0;
506 last_cluster = buffer->info[0].cluster;
507 for (i = 1; i < count; i++) {
508 if (last_cluster != buffer->info[i].cluster) {
509 reverse_range (buffer, start, i);
510 start = i;
511 last_cluster = buffer->info[i].cluster;
512 }
513 }
514 reverse_range (buffer, start, i);
515 } 729 }
516 730
731 void
732 hb_buffer_guess_properties (hb_buffer_t *buffer)
733 {
734 buffer->guess_properties ();
735 }
517 736
518 #define ADD_UTF(T) \ 737 #define ADD_UTF(T) \
519 HB_STMT_START { \ 738 HB_STMT_START { \
739 if (text_length == -1) { \
740 text_length = 0; \
741 const T *p = (const T *) text; \
742 while (*p) { \
743 text_length++; \
744 p++; \
745 } \
746 } \
747 if (item_length == -1) \
748 item_length = text_length - item_offset; \
749 buffer->ensure (buffer->len + item_length * sizeof (T) / 4); \
520 const T *next = (const T *) text + item_offset; \ 750 const T *next = (const T *) text + item_offset; \
521 const T *end = next + item_length; \ 751 const T *end = next + item_length; \
522 while (next < end) { \ 752 while (next < end) { \
523 hb_codepoint_t u; \ 753 hb_codepoint_t u; \
524 const T *old_next = next; \ 754 const T *old_next = next; \
525 next = UTF_NEXT (next, end, u); \ 755 next = UTF_NEXT (next, end, u); \
526 » hb_buffer_add_glyph (buffer, u, 1, old_next - (const T *) text); \ 756 » hb_buffer_add (buffer, u, 1, old_next - (const T *) text); \
527 } \ 757 } \
528 } HB_STMT_END 758 } HB_STMT_END
529 759
530 760
531 #define UTF8_COMPUTE(Char, Mask, Len) \ 761 #define UTF8_COMPUTE(Char, Mask, Len) \
532 if (Char < 128) { Len = 1; Mask = 0x7f; } \ 762 if (Char < 128) { Len = 1; Mask = 0x7f; } \
533 else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \ 763 else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
534 else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \ 764 else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
535 else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \ 765 else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
536 else Len = 0; 766 else Len = 0;
537 767
538 static inline const uint8_t * 768 static inline const uint8_t *
539 hb_utf8_next (const uint8_t *text, 769 hb_utf8_next (const uint8_t *text,
540 const uint8_t *end, 770 const uint8_t *end,
541 hb_codepoint_t *unicode) 771 hb_codepoint_t *unicode)
542 { 772 {
543 uint8_t c = *text; 773 uint8_t c = *text;
544 unsigned int mask, len; 774 unsigned int mask, len;
545 775
546 /* TODO check for overlong sequences? also: optimize? */ 776 /* TODO check for overlong sequences? */
547 777
548 UTF8_COMPUTE (c, mask, len); 778 UTF8_COMPUTE (c, mask, len);
549 if (unlikely (!len || (unsigned int) (end - text) < len)) { 779 if (unlikely (!len || (unsigned int) (end - text) < len)) {
550 *unicode = -1; 780 *unicode = -1;
551 return text + 1; 781 return text + 1;
552 } else { 782 } else {
553 hb_codepoint_t result; 783 hb_codepoint_t result;
554 unsigned int i; 784 unsigned int i;
555 result = c & mask; 785 result = c & mask;
556 for (i = 1; i < len; i++) 786 for (i = 1; i < len; i++)
557 { 787 {
558 if (unlikely ((text[i] & 0xc0) != 0x80)) 788 if (unlikely ((text[i] & 0xc0) != 0x80))
559 { 789 {
560 *unicode = -1; 790 *unicode = -1;
561 return text + 1; 791 return text + 1;
562 } 792 }
563 result <<= 6; 793 result <<= 6;
564 result |= (text[i] & 0x3f); 794 result |= (text[i] & 0x3f);
565 } 795 }
566 *unicode = result; 796 *unicode = result;
567 return text + len; 797 return text + len;
568 } 798 }
569 } 799 }
570 800
571 void 801 void
572 hb_buffer_add_utf8 (hb_buffer_t *buffer, 802 hb_buffer_add_utf8 (hb_buffer_t *buffer,
573 const char *text, 803 const char *text,
574 » » unsigned int text_length HB_UNUSED, 804 » » int text_length,
575 unsigned int item_offset, 805 unsigned int item_offset,
576 » » unsigned int item_length) 806 » » int item_length)
577 { 807 {
578 #define UTF_NEXT(S, E, U) hb_utf8_next (S, E, &(U)) 808 #define UTF_NEXT(S, E, U) hb_utf8_next (S, E, &(U))
579 ADD_UTF (uint8_t); 809 ADD_UTF (uint8_t);
580 #undef UTF_NEXT 810 #undef UTF_NEXT
581 } 811 }
582 812
583 static inline const uint16_t * 813 static inline const uint16_t *
584 hb_utf16_next (const uint16_t *text, 814 hb_utf16_next (const uint16_t *text,
585 const uint16_t *end, 815 const uint16_t *end,
586 hb_codepoint_t *unicode) 816 hb_codepoint_t *unicode)
587 { 817 {
588 uint16_t c = *text++; 818 uint16_t c = *text++;
589 819
590 if (unlikely (c >= 0xd800 && c < 0xdc00)) { 820 if (unlikely (c >= 0xd800 && c < 0xdc00)) {
591 /* high surrogate */ 821 /* high surrogate */
592 uint16_t l; 822 uint16_t l;
593 if (text < end && ((l = *text), unlikely (l >= 0xdc00 && l < 0xe000))) { 823 if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
594 /* low surrogate */ 824 /* low surrogate */
595 *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x100 00); 825 *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x100 00);
596 text++; 826 text++;
597 } else 827 } else
598 *unicode = -1; 828 *unicode = -1;
599 } else 829 } else
600 *unicode = c; 830 *unicode = c;
601 831
602 return text; 832 return text;
603 } 833 }
604 834
605 void 835 void
606 hb_buffer_add_utf16 (hb_buffer_t *buffer, 836 hb_buffer_add_utf16 (hb_buffer_t *buffer,
607 const uint16_t *text, 837 const uint16_t *text,
608 » » unsigned int text_length HB_UNUSED, 838 » » int text_length,
609 unsigned int item_offset, 839 unsigned int item_offset,
610 » » unsigned int item_length) 840 » » int item_length)
611 { 841 {
612 #define UTF_NEXT(S, E, U) hb_utf16_next (S, E, &(U)) 842 #define UTF_NEXT(S, E, U) hb_utf16_next (S, E, &(U))
613 ADD_UTF (uint16_t); 843 ADD_UTF (uint16_t);
614 #undef UTF_NEXT 844 #undef UTF_NEXT
615 } 845 }
616 846
617 void 847 void
618 hb_buffer_add_utf32 (hb_buffer_t *buffer, 848 hb_buffer_add_utf32 (hb_buffer_t *buffer,
619 const uint32_t *text, 849 const uint32_t *text,
620 » » unsigned int text_length HB_UNUSED, 850 » » int text_length,
621 unsigned int item_offset, 851 unsigned int item_offset,
622 » » unsigned int item_length) 852 » » int item_length)
623 { 853 {
624 #define UTF_NEXT(S, E, U) ((U) = *(S), (S)+1) 854 #define UTF_NEXT(S, E, U) ((U) = *(S), (S)+1)
625 ADD_UTF (uint32_t); 855 ADD_UTF (uint32_t);
626 #undef UTF_NEXT 856 #undef UTF_NEXT
627 } 857 }
628 858
629 859
630 HB_END_DECLS
OLDNEW
« no previous file with comments | « third_party/harfbuzz-ng/src/hb-buffer.h ('k') | third_party/harfbuzz-ng/src/hb-buffer-private.hh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698