OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 1998-2004 David Turner and Werner Lemberg | 2 * Copyright © 1998-2004 David Turner and Werner Lemberg |
3 * Copyright © 2004,2007,2009,2010 Red Hat, Inc. | 3 * Copyright © 2004,2007,2009,2010 Red Hat, Inc. |
4 * Copyright © 2011 Google, Inc. | 4 * Copyright © 2011 Google, Inc. |
5 * | 5 * |
6 * This is part of HarfBuzz, a text shaping library. | 6 * This is part of HarfBuzz, a text shaping library. |
7 * | 7 * |
8 * Permission is hereby granted, without written agreement and without | 8 * Permission is hereby granted, without written agreement and without |
9 * license or royalty fees, to use, copy, modify, and distribute this | 9 * license or royalty fees, to use, copy, modify, and distribute this |
10 * software and its documentation for any purpose, provided that the | 10 * software and its documentation for any purpose, provided that the |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "hb-buffer-private.hh" | 30 #include "hb-buffer-private.hh" |
31 | 31 |
32 #include <string.h> | 32 #include <string.h> |
33 | 33 |
34 | 34 |
35 | 35 |
36 #ifndef HB_DEBUG_BUFFER | 36 #ifndef HB_DEBUG_BUFFER |
37 #define HB_DEBUG_BUFFER (HB_DEBUG+0) | 37 #define HB_DEBUG_BUFFER (HB_DEBUG+0) |
38 #endif | 38 #endif |
39 | 39 |
40 #define _HB_BUFFER_UNICODE_FUNCS_DEFAULT (const_cast<hb_unicode_funcs_t *> (&_hb
_unicode_funcs_default)) | |
41 #define _HB_BUFFER_PROPS_DEFAULT { HB_DIRECTION_INVALID, HB_SCRIPT_INVALID, HB_L
ANGUAGE_INVALID } | |
42 | |
43 /* Here is how the buffer works internally: | 40 /* Here is how the buffer works internally: |
44 * | 41 * |
45 * There are two info pointers: info and out_info. They always have | 42 * There are two info pointers: info and out_info. They always have |
46 * the same allocated size, but different lengths. | 43 * the same allocated size, but different lengths. |
47 * | 44 * |
48 * As an optimization, both info and out_info may point to the | 45 * As an optimization, both info and out_info may point to the |
49 * same piece of memory, which is owned by info. This remains the | 46 * same piece of memory, which is owned by info. This remains the |
50 * case as long as out_len doesn't exceed i at any time. | 47 * case as long as out_len doesn't exceed i at any time. |
51 * In that case, swap_buffers() is no-op and the glyph operations operate | 48 * In that case, swap_buffers() is no-op and the glyph operations operate |
52 * mostly in-place. | 49 * mostly in-place. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 } | 116 } |
120 | 117 |
121 return true; | 118 return true; |
122 } | 119 } |
123 | 120 |
124 void * | 121 void * |
125 hb_buffer_t::get_scratch_buffer (unsigned int *size) | 122 hb_buffer_t::get_scratch_buffer (unsigned int *size) |
126 { | 123 { |
127 have_output = false; | 124 have_output = false; |
128 have_positions = false; | 125 have_positions = false; |
| 126 |
129 out_len = 0; | 127 out_len = 0; |
| 128 out_info = info; |
| 129 |
130 *size = allocated * sizeof (pos[0]); | 130 *size = allocated * sizeof (pos[0]); |
131 return pos; | 131 return pos; |
132 } | 132 } |
133 | 133 |
134 | 134 |
| 135 |
135 /* HarfBuzz-Internal API */ | 136 /* HarfBuzz-Internal API */ |
136 | 137 |
137 void | 138 void |
138 hb_buffer_t::reset (void) | 139 hb_buffer_t::reset (void) |
139 { | 140 { |
140 if (unlikely (hb_object_is_inert (this))) | 141 if (unlikely (hb_object_is_inert (this))) |
141 return; | 142 return; |
142 | 143 |
143 hb_unicode_funcs_destroy (unicode); | 144 hb_unicode_funcs_destroy (unicode); |
144 unicode = _HB_BUFFER_UNICODE_FUNCS_DEFAULT; | 145 unicode = hb_unicode_funcs_get_default (); |
145 | 146 |
146 hb_segment_properties_t default_props = _HB_BUFFER_PROPS_DEFAULT; | 147 hb_segment_properties_t default_props = _HB_BUFFER_PROPS_DEFAULT; |
147 props = default_props; | 148 props = default_props; |
148 | 149 |
| 150 content_type = HB_BUFFER_CONTENT_TYPE_INVALID; |
149 in_error = false; | 151 in_error = false; |
150 have_output = false; | 152 have_output = false; |
151 have_positions = false; | 153 have_positions = false; |
152 | 154 |
153 idx = 0; | 155 idx = 0; |
154 len = 0; | 156 len = 0; |
155 out_len = 0; | 157 out_len = 0; |
| 158 out_info = info; |
156 | 159 |
157 serial = 0; | 160 serial = 0; |
158 memset (allocated_var_bytes, 0, sizeof allocated_var_bytes); | 161 memset (allocated_var_bytes, 0, sizeof allocated_var_bytes); |
159 memset (allocated_var_owner, 0, sizeof allocated_var_owner); | 162 memset (allocated_var_owner, 0, sizeof allocated_var_owner); |
160 | |
161 out_info = info; | |
162 } | 163 } |
163 | 164 |
164 void | 165 void |
165 hb_buffer_t::add (hb_codepoint_t codepoint, | 166 hb_buffer_t::add (hb_codepoint_t codepoint, |
166 hb_mask_t mask, | 167 hb_mask_t mask, |
167 unsigned int cluster) | 168 unsigned int cluster) |
168 { | 169 { |
169 hb_glyph_info_t *glyph; | 170 hb_glyph_info_t *glyph; |
170 | 171 |
171 if (unlikely (!ensure (len + 1))) return; | 172 if (unlikely (!ensure (len + 1))) return; |
(...skipping 23 matching lines...) Expand all Loading... |
195 | 196 |
196 void | 197 void |
197 hb_buffer_t::clear_positions (void) | 198 hb_buffer_t::clear_positions (void) |
198 { | 199 { |
199 if (unlikely (hb_object_is_inert (this))) | 200 if (unlikely (hb_object_is_inert (this))) |
200 return; | 201 return; |
201 | 202 |
202 have_output = false; | 203 have_output = false; |
203 have_positions = true; | 204 have_positions = true; |
204 | 205 |
| 206 out_len = 0; |
| 207 out_info = info; |
| 208 |
205 memset (pos, 0, sizeof (pos[0]) * len); | 209 memset (pos, 0, sizeof (pos[0]) * len); |
206 } | 210 } |
207 | 211 |
208 void | 212 void |
209 hb_buffer_t::swap_buffers (void) | 213 hb_buffer_t::swap_buffers (void) |
210 { | 214 { |
211 if (unlikely (in_error)) return; | 215 if (unlikely (in_error)) return; |
212 | 216 |
213 assert (have_output); | 217 assert (have_output); |
214 have_output = false; | 218 have_output = false; |
215 | 219 |
216 if (out_info != info) | 220 if (out_info != info) |
217 { | 221 { |
218 hb_glyph_info_t *tmp_string; | 222 hb_glyph_info_t *tmp_string; |
219 tmp_string = info; | 223 tmp_string = info; |
220 info = out_info; | 224 info = out_info; |
221 out_info = tmp_string; | 225 out_info = tmp_string; |
222 pos = (hb_glyph_position_t *) out_info; | 226 pos = (hb_glyph_position_t *) out_info; |
223 } | 227 } |
224 | 228 |
225 unsigned int tmp; | 229 unsigned int tmp; |
226 tmp = len; | 230 tmp = len; |
227 len = out_len; | 231 len = out_len; |
228 out_len = tmp; | 232 out_len = tmp; |
229 | 233 |
230 idx = 0; | 234 idx = 0; |
231 } | 235 } |
232 | 236 |
233 void | |
234 hb_buffer_t::replace_glyphs_be16 (unsigned int num_in, | |
235 unsigned int num_out, | |
236 const char *glyph_data_be) | |
237 { | |
238 if (!make_room_for (num_in, num_out)) return; | |
239 | |
240 hb_glyph_info_t orig_info = info[idx]; | |
241 for (unsigned int i = 1; i < num_in; i++) | |
242 { | |
243 hb_glyph_info_t *inf = &info[idx + i]; | |
244 orig_info.cluster = MIN (orig_info.cluster, inf->cluster); | |
245 } | |
246 | |
247 hb_glyph_info_t *pinfo = &out_info[out_len]; | |
248 const unsigned char *data = (const unsigned char *) glyph_data_be; | |
249 for (unsigned int i = 0; i < num_out; i++) | |
250 { | |
251 *pinfo = orig_info; | |
252 pinfo->codepoint = (data[2*i] << 8) | data[2*i+1]; | |
253 pinfo++; | |
254 } | |
255 | |
256 idx += num_in; | |
257 out_len += num_out; | |
258 } | |
259 | 237 |
260 void | 238 void |
261 hb_buffer_t::replace_glyphs (unsigned int num_in, | 239 hb_buffer_t::replace_glyphs (unsigned int num_in, |
262 unsigned int num_out, | 240 unsigned int num_out, |
263 const uint32_t *glyph_data) | 241 const uint32_t *glyph_data) |
264 { | 242 { |
265 if (!make_room_for (num_in, num_out)) return; | 243 if (unlikely (!make_room_for (num_in, num_out))) return; |
| 244 |
| 245 merge_clusters (idx, idx + num_in); |
266 | 246 |
267 hb_glyph_info_t orig_info = info[idx]; | 247 hb_glyph_info_t orig_info = info[idx]; |
268 for (unsigned int i = 1; i < num_in; i++) | |
269 { | |
270 hb_glyph_info_t *inf = &info[idx + i]; | |
271 orig_info.cluster = MIN (orig_info.cluster, inf->cluster); | |
272 } | |
273 | |
274 hb_glyph_info_t *pinfo = &out_info[out_len]; | 248 hb_glyph_info_t *pinfo = &out_info[out_len]; |
275 for (unsigned int i = 0; i < num_out; i++) | 249 for (unsigned int i = 0; i < num_out; i++) |
276 { | 250 { |
277 *pinfo = orig_info; | 251 *pinfo = orig_info; |
278 pinfo->codepoint = glyph_data[i]; | 252 pinfo->codepoint = glyph_data[i]; |
279 pinfo++; | 253 pinfo++; |
280 } | 254 } |
281 | 255 |
282 idx += num_in; | 256 idx += num_in; |
283 out_len += num_out; | 257 out_len += num_out; |
284 } | 258 } |
285 | 259 |
286 void | 260 void |
287 hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) | 261 hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) |
288 { | 262 { |
289 if (!make_room_for (0, 1)) return; | 263 if (unlikely (!make_room_for (0, 1))) return; |
290 | 264 |
291 out_info[out_len] = info[idx]; | 265 out_info[out_len] = info[idx]; |
292 out_info[out_len].codepoint = glyph_index; | 266 out_info[out_len].codepoint = glyph_index; |
293 | 267 |
294 out_len++; | 268 out_len++; |
295 } | 269 } |
296 | 270 |
297 void | 271 void |
| 272 hb_buffer_t::output_info (hb_glyph_info_t &glyph_info) |
| 273 { |
| 274 if (unlikely (!make_room_for (0, 1))) return; |
| 275 |
| 276 out_info[out_len] = glyph_info; |
| 277 |
| 278 out_len++; |
| 279 } |
| 280 |
| 281 void |
298 hb_buffer_t::copy_glyph (void) | 282 hb_buffer_t::copy_glyph (void) |
299 { | 283 { |
300 if (!make_room_for (0, 1)) return; | 284 if (unlikely (!make_room_for (0, 1))) return; |
301 | 285 |
302 out_info[out_len] = info[idx]; | 286 out_info[out_len] = info[idx]; |
303 | 287 |
304 out_len++; | 288 out_len++; |
305 } | 289 } |
306 | 290 |
307 void | 291 void |
308 hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) | 292 hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) |
309 { | 293 { |
310 if (!make_room_for (1, 1)) return; | 294 if (unlikely (out_info != info || out_len != idx)) { |
311 | 295 if (unlikely (!make_room_for (1, 1))) return; |
312 out_info[out_len] = info[idx]; | 296 out_info[out_len] = info[idx]; |
| 297 } |
313 out_info[out_len].codepoint = glyph_index; | 298 out_info[out_len].codepoint = glyph_index; |
314 | 299 |
315 idx++; | 300 idx++; |
316 out_len++; | 301 out_len++; |
317 } | 302 } |
318 | 303 |
319 void | |
320 hb_buffer_t::next_glyph (void) | |
321 { | |
322 if (have_output) | |
323 { | |
324 if (out_info != info) | |
325 { | |
326 if (unlikely (!ensure (out_len + 1))) return; | |
327 out_info[out_len] = info[idx]; | |
328 } | |
329 else if (out_len != idx) | |
330 out_info[out_len] = info[idx]; | |
331 | |
332 out_len++; | |
333 } | |
334 | |
335 idx++; | |
336 } | |
337 | 304 |
338 void | 305 void |
339 hb_buffer_t::set_masks (hb_mask_t value, | 306 hb_buffer_t::set_masks (hb_mask_t value, |
340 hb_mask_t mask, | 307 hb_mask_t mask, |
341 unsigned int cluster_start, | 308 unsigned int cluster_start, |
342 unsigned int cluster_end) | 309 unsigned int cluster_end) |
343 { | 310 { |
344 hb_mask_t not_mask = ~mask; | 311 hb_mask_t not_mask = ~mask; |
345 value &= mask; | 312 value &= mask; |
346 | 313 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 last_cluster = info[i].cluster; | 384 last_cluster = info[i].cluster; |
418 } | 385 } |
419 } | 386 } |
420 reverse_range (start, i); | 387 reverse_range (start, i); |
421 } | 388 } |
422 | 389 |
423 void | 390 void |
424 hb_buffer_t::merge_clusters (unsigned int start, | 391 hb_buffer_t::merge_clusters (unsigned int start, |
425 unsigned int end) | 392 unsigned int end) |
426 { | 393 { |
427 unsigned int cluster = this->info[start].cluster; | 394 if (unlikely (end - start < 2)) |
| 395 return; |
| 396 |
| 397 unsigned int cluster = info[start].cluster; |
428 | 398 |
429 for (unsigned int i = start + 1; i < end; i++) | 399 for (unsigned int i = start + 1; i < end; i++) |
430 cluster = MIN (cluster, this->info[i].cluster); | 400 cluster = MIN (cluster, info[i].cluster); |
| 401 |
| 402 /* Extend end */ |
| 403 while (end < len && info[end - 1].cluster == info[end].cluster) |
| 404 end++; |
| 405 |
| 406 /* Extend start */ |
| 407 while (idx < start && info[start - 1].cluster == info[start].cluster) |
| 408 start--; |
| 409 |
| 410 /* If we hit the start of buffer, continue in out-buffer. */ |
| 411 if (idx == start) |
| 412 for (unsigned i = out_len; i && out_info[i - 1].cluster == info[start].clust
er; i--) |
| 413 out_info[i - 1].cluster = cluster; |
| 414 |
431 for (unsigned int i = start; i < end; i++) | 415 for (unsigned int i = start; i < end; i++) |
432 this->info[i].cluster = cluster; | 416 info[i].cluster = cluster; |
433 } | 417 } |
434 void | 418 void |
435 hb_buffer_t::merge_out_clusters (unsigned int start, | 419 hb_buffer_t::merge_out_clusters (unsigned int start, |
436 unsigned int end) | 420 unsigned int end) |
437 { | 421 { |
438 unsigned int cluster = this->out_info[start].cluster; | 422 if (unlikely (end - start < 2)) |
| 423 return; |
| 424 |
| 425 unsigned int cluster = out_info[start].cluster; |
439 | 426 |
440 for (unsigned int i = start + 1; i < end; i++) | 427 for (unsigned int i = start + 1; i < end; i++) |
441 cluster = MIN (cluster, this->out_info[i].cluster); | 428 cluster = MIN (cluster, out_info[i].cluster); |
| 429 |
| 430 /* Extend start */ |
| 431 while (start && out_info[start - 1].cluster == out_info[start].cluster) |
| 432 start--; |
| 433 |
| 434 /* Extend end */ |
| 435 while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster) |
| 436 end++; |
| 437 |
| 438 /* If we hit the end of out-buffer, continue in buffer. */ |
| 439 if (end == out_len) |
| 440 for (unsigned i = idx; i < len && info[i].cluster == out_info[end - 1].clust
er; i++) |
| 441 info[i].cluster = cluster; |
| 442 |
442 for (unsigned int i = start; i < end; i++) | 443 for (unsigned int i = start; i < end; i++) |
443 this->out_info[i].cluster = cluster; | 444 out_info[i].cluster = cluster; |
444 } | 445 } |
445 | 446 |
446 void | 447 void |
447 hb_buffer_t::guess_properties (void) | 448 hb_buffer_t::guess_properties (void) |
448 { | 449 { |
| 450 if (unlikely (!len)) return; |
| 451 assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); |
| 452 |
449 /* If script is set to INVALID, guess from buffer contents */ | 453 /* If script is set to INVALID, guess from buffer contents */ |
450 if (props.script == HB_SCRIPT_INVALID) { | 454 if (props.script == HB_SCRIPT_INVALID) { |
451 for (unsigned int i = 0; i < len; i++) { | 455 for (unsigned int i = 0; i < len; i++) { |
452 hb_script_t script = hb_unicode_script (unicode, info[i].codepoint); | 456 hb_script_t script = unicode->script (info[i].codepoint); |
453 if (likely (script != HB_SCRIPT_COMMON && | 457 if (likely (script != HB_SCRIPT_COMMON && |
454 script != HB_SCRIPT_INHERITED && | 458 script != HB_SCRIPT_INHERITED && |
455 script != HB_SCRIPT_UNKNOWN)) { | 459 script != HB_SCRIPT_UNKNOWN)) { |
456 props.script = script; | 460 props.script = script; |
457 break; | 461 break; |
458 } | 462 } |
459 } | 463 } |
460 } | 464 } |
461 | 465 |
462 /* If direction is set to INVALID, guess from script */ | 466 /* If direction is set to INVALID, guess from script */ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 byte_i, byte_i + count - 1, owner); | 515 byte_i, byte_i + count - 1, owner); |
512 | 516 |
513 assert (byte_i < 8 && byte_i + count <= 8); | 517 assert (byte_i < 8 && byte_i + count <= 8); |
514 for (unsigned int i = byte_i; i < byte_i + count; i++) { | 518 for (unsigned int i = byte_i; i < byte_i + count; i++) { |
515 assert (allocated_var_bytes[i]); | 519 assert (allocated_var_bytes[i]); |
516 assert (0 == strcmp (allocated_var_owner[i], owner)); | 520 assert (0 == strcmp (allocated_var_owner[i], owner)); |
517 allocated_var_bytes[i]--; | 521 allocated_var_bytes[i]--; |
518 } | 522 } |
519 } | 523 } |
520 | 524 |
| 525 void hb_buffer_t::assert_var (unsigned int byte_i, unsigned int count, const cha
r *owner) |
| 526 { |
| 527 if (DEBUG (BUFFER)) |
| 528 dump_var_allocation (this); |
| 529 |
| 530 DEBUG_MSG (BUFFER, this, |
| 531 "Asserting var bytes %d..%d for %s", |
| 532 byte_i, byte_i + count - 1, owner); |
| 533 |
| 534 assert (byte_i < 8 && byte_i + count <= 8); |
| 535 for (unsigned int i = byte_i; i < byte_i + count; i++) { |
| 536 assert (allocated_var_bytes[i]); |
| 537 assert (0 == strcmp (allocated_var_owner[i], owner)); |
| 538 } |
| 539 } |
| 540 |
521 void hb_buffer_t::deallocate_var_all (void) | 541 void hb_buffer_t::deallocate_var_all (void) |
522 { | 542 { |
523 memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes)); | 543 memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes)); |
524 memset (allocated_var_owner, 0, sizeof (allocated_var_owner)); | 544 memset (allocated_var_owner, 0, sizeof (allocated_var_owner)); |
525 } | 545 } |
526 | 546 |
527 /* Public API */ | 547 /* Public API */ |
528 | 548 |
529 hb_buffer_t * | 549 hb_buffer_t * |
530 hb_buffer_create () | 550 hb_buffer_create () |
531 { | 551 { |
532 hb_buffer_t *buffer; | 552 hb_buffer_t *buffer; |
533 | 553 |
534 if (!(buffer = hb_object_create<hb_buffer_t> ())) | 554 if (!(buffer = hb_object_create<hb_buffer_t> ())) |
535 return hb_buffer_get_empty (); | 555 return hb_buffer_get_empty (); |
536 | 556 |
537 buffer->reset (); | 557 buffer->reset (); |
538 | 558 |
539 return buffer; | 559 return buffer; |
540 } | 560 } |
541 | 561 |
542 hb_buffer_t * | 562 hb_buffer_t * |
543 hb_buffer_get_empty (void) | 563 hb_buffer_get_empty (void) |
544 { | 564 { |
545 static const hb_buffer_t _hb_buffer_nil = { | 565 static const hb_buffer_t _hb_buffer_nil = { |
546 HB_OBJECT_HEADER_STATIC, | 566 HB_OBJECT_HEADER_STATIC, |
547 | 567 |
548 _HB_BUFFER_UNICODE_FUNCS_DEFAULT, | 568 const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil), |
549 _HB_BUFFER_PROPS_DEFAULT, | 569 _HB_BUFFER_PROPS_DEFAULT, |
550 | 570 |
| 571 HB_BUFFER_CONTENT_TYPE_INVALID, |
551 true, /* in_error */ | 572 true, /* in_error */ |
552 true, /* have_output */ | 573 true, /* have_output */ |
553 true /* have_positions */ | 574 true /* have_positions */ |
554 }; | 575 }; |
555 | 576 |
556 return const_cast<hb_buffer_t *> (&_hb_buffer_nil); | 577 return const_cast<hb_buffer_t *> (&_hb_buffer_nil); |
557 } | 578 } |
558 | 579 |
559 hb_buffer_t * | 580 hb_buffer_t * |
560 hb_buffer_reference (hb_buffer_t *buffer) | 581 hb_buffer_reference (hb_buffer_t *buffer) |
(...skipping 26 matching lines...) Expand all Loading... |
587 | 608 |
588 void * | 609 void * |
589 hb_buffer_get_user_data (hb_buffer_t *buffer, | 610 hb_buffer_get_user_data (hb_buffer_t *buffer, |
590 hb_user_data_key_t *key) | 611 hb_user_data_key_t *key) |
591 { | 612 { |
592 return hb_object_get_user_data (buffer, key); | 613 return hb_object_get_user_data (buffer, key); |
593 } | 614 } |
594 | 615 |
595 | 616 |
596 void | 617 void |
| 618 hb_buffer_set_content_type (hb_buffer_t *buffer, |
| 619 hb_buffer_content_type_t content_type) |
| 620 { |
| 621 buffer->content_type = content_type; |
| 622 } |
| 623 |
| 624 hb_buffer_content_type_t |
| 625 hb_buffer_get_content_type (hb_buffer_t *buffer) |
| 626 { |
| 627 return buffer->content_type; |
| 628 } |
| 629 |
| 630 |
| 631 void |
597 hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, | 632 hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, |
598 hb_unicode_funcs_t *unicode) | 633 hb_unicode_funcs_t *unicode) |
599 { | 634 { |
600 if (unlikely (hb_object_is_inert (buffer))) | 635 if (unlikely (hb_object_is_inert (buffer))) |
601 return; | 636 return; |
602 | 637 |
603 if (!unicode) | 638 if (!unicode) |
604 unicode = _HB_BUFFER_UNICODE_FUNCS_DEFAULT; | 639 unicode = hb_unicode_funcs_get_default (); |
| 640 |
605 | 641 |
606 hb_unicode_funcs_reference (unicode); | 642 hb_unicode_funcs_reference (unicode); |
607 hb_unicode_funcs_destroy (buffer->unicode); | 643 hb_unicode_funcs_destroy (buffer->unicode); |
608 buffer->unicode = unicode; | 644 buffer->unicode = unicode; |
609 } | 645 } |
610 | 646 |
611 hb_unicode_funcs_t * | 647 hb_unicode_funcs_t * |
612 hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) | 648 hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) |
613 { | 649 { |
614 return buffer->unicode; | 650 return buffer->unicode; |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 } | 861 } |
826 } | 862 } |
827 | 863 |
828 void | 864 void |
829 hb_buffer_add_utf8 (hb_buffer_t *buffer, | 865 hb_buffer_add_utf8 (hb_buffer_t *buffer, |
830 const char *text, | 866 const char *text, |
831 int text_length, | 867 int text_length, |
832 unsigned int item_offset, | 868 unsigned int item_offset, |
833 int item_length) | 869 int item_length) |
834 { | 870 { |
| 871 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || |
| 872 (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALI
D)); |
| 873 if (unlikely (hb_object_is_inert (buffer))) |
| 874 return; |
| 875 buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; |
835 #define UTF_NEXT(S, E, U) hb_utf8_next (S, E, &(U)) | 876 #define UTF_NEXT(S, E, U) hb_utf8_next (S, E, &(U)) |
836 ADD_UTF (uint8_t); | 877 ADD_UTF (uint8_t); |
837 #undef UTF_NEXT | 878 #undef UTF_NEXT |
838 } | 879 } |
839 | 880 |
840 static inline const uint16_t * | 881 static inline const uint16_t * |
841 hb_utf16_next (const uint16_t *text, | 882 hb_utf16_next (const uint16_t *text, |
842 const uint16_t *end, | 883 const uint16_t *end, |
843 hb_codepoint_t *unicode) | 884 hb_codepoint_t *unicode) |
844 { | 885 { |
(...skipping 14 matching lines...) Expand all Loading... |
859 return text; | 900 return text; |
860 } | 901 } |
861 | 902 |
862 void | 903 void |
863 hb_buffer_add_utf16 (hb_buffer_t *buffer, | 904 hb_buffer_add_utf16 (hb_buffer_t *buffer, |
864 const uint16_t *text, | 905 const uint16_t *text, |
865 int text_length, | 906 int text_length, |
866 unsigned int item_offset, | 907 unsigned int item_offset, |
867 int item_length) | 908 int item_length) |
868 { | 909 { |
| 910 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || |
| 911 (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALI
D)); |
| 912 if (unlikely (hb_object_is_inert (buffer))) |
| 913 return; |
| 914 buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; |
869 #define UTF_NEXT(S, E, U) hb_utf16_next (S, E, &(U)) | 915 #define UTF_NEXT(S, E, U) hb_utf16_next (S, E, &(U)) |
870 ADD_UTF (uint16_t); | 916 ADD_UTF (uint16_t); |
871 #undef UTF_NEXT | 917 #undef UTF_NEXT |
872 } | 918 } |
873 | 919 |
874 void | 920 void |
875 hb_buffer_add_utf32 (hb_buffer_t *buffer, | 921 hb_buffer_add_utf32 (hb_buffer_t *buffer, |
876 const uint32_t *text, | 922 const uint32_t *text, |
877 int text_length, | 923 int text_length, |
878 unsigned int item_offset, | 924 unsigned int item_offset, |
879 int item_length) | 925 int item_length) |
880 { | 926 { |
| 927 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || |
| 928 (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALI
D)); |
| 929 if (unlikely (hb_object_is_inert (buffer))) |
| 930 return; |
| 931 buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; |
881 #define UTF_NEXT(S, E, U) ((U) = *(S), (S)+1) | 932 #define UTF_NEXT(S, E, U) ((U) = *(S), (S)+1) |
882 ADD_UTF (uint32_t); | 933 ADD_UTF (uint32_t); |
883 #undef UTF_NEXT | 934 #undef UTF_NEXT |
884 } | 935 } |
885 | 936 |
886 | 937 |
| 938 static int |
| 939 compare_info_codepoint (const hb_glyph_info_t *pa, |
| 940 const hb_glyph_info_t *pb) |
| 941 { |
| 942 return (int) pb->codepoint - (int) pa->codepoint; |
| 943 } |
| 944 |
| 945 static inline void |
| 946 normalize_glyphs_cluster (hb_buffer_t *buffer, |
| 947 unsigned int start, |
| 948 unsigned int end, |
| 949 bool backward) |
| 950 { |
| 951 hb_glyph_position_t *pos = buffer->pos; |
| 952 |
| 953 /* Total cluster advance */ |
| 954 hb_position_t total_x_advance = 0, total_y_advance = 0; |
| 955 for (unsigned int i = start; i < end; i++) |
| 956 { |
| 957 total_x_advance += pos[i].x_advance; |
| 958 total_y_advance += pos[i].y_advance; |
| 959 } |
| 960 |
| 961 hb_position_t x_advance = 0, y_advance = 0; |
| 962 for (unsigned int i = start; i < end; i++) |
| 963 { |
| 964 pos[i].x_offset += x_advance; |
| 965 pos[i].y_offset += y_advance; |
| 966 |
| 967 x_advance += pos[i].x_advance; |
| 968 y_advance += pos[i].y_advance; |
| 969 |
| 970 pos[i].x_advance = 0; |
| 971 pos[i].y_advance = 0; |
| 972 } |
| 973 |
| 974 if (backward) |
| 975 { |
| 976 /* Transfer all cluster advance to the last glyph. */ |
| 977 pos[end - 1].x_advance = total_x_advance; |
| 978 pos[end - 1].y_advance = total_y_advance; |
| 979 |
| 980 hb_bubble_sort (buffer->info + start, end - start - 1, compare_info_codepoin
t, buffer->pos + start); |
| 981 } else { |
| 982 /* Transfer all cluster advance to the first glyph. */ |
| 983 pos[start].x_advance += total_x_advance; |
| 984 pos[start].y_advance += total_y_advance; |
| 985 for (unsigned int i = start + 1; i < end; i++) { |
| 986 pos[i].x_offset -= total_x_advance; |
| 987 pos[i].y_offset -= total_y_advance; |
| 988 } |
| 989 hb_bubble_sort (buffer->info + start + 1, end - start - 1, compare_info_code
point, buffer->pos + start + 1); |
| 990 } |
| 991 } |
| 992 |
| 993 void |
| 994 hb_buffer_normalize_glyphs (hb_buffer_t *buffer) |
| 995 { |
| 996 assert (buffer->have_positions); |
| 997 /* XXX assert (buffer->have_glyphs); */ |
| 998 |
| 999 bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); |
| 1000 |
| 1001 unsigned int count = buffer->len; |
| 1002 if (unlikely (!count)) return; |
| 1003 hb_glyph_info_t *info = buffer->info; |
| 1004 |
| 1005 unsigned int start = 0; |
| 1006 unsigned int end; |
| 1007 for (end = start + 1; end < count; end++) |
| 1008 if (info[start].cluster != info[end].cluster) { |
| 1009 normalize_glyphs_cluster (buffer, start, end, backward); |
| 1010 start = end; |
| 1011 } |
| 1012 normalize_glyphs_cluster (buffer, start, end, backward); |
| 1013 } |
OLD | NEW |