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

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

Issue 10915172: harfbuzz-ng roll (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 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 © 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
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
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
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
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
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
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
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
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 }
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