Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1892 | Rev 3959 | ||
---|---|---|---|
Line 38... | Line 38... | ||
38 | * Chris Wilson |
38 | * Chris Wilson |
39 | */ |
39 | */ |
Line 40... | Line 40... | ||
40 | 40 | ||
41 | #include "cairoint.h" |
41 | #include "cairoint.h" |
- | 42 | #include "cairo-error-private.h" |
|
- | 43 | #include "cairo-image-surface-private.h" |
|
- | 44 | #include "cairo-list-inline.h" |
|
42 | #include "cairo-error-private.h" |
45 | #include "cairo-pattern-private.h" |
- | 46 | #include "cairo-scaled-font-private.h" |
|
Line 43... | Line 47... | ||
43 | #include "cairo-scaled-font-private.h" |
47 | #include "cairo-surface-backend-private.h" |
44 | 48 | ||
45 | #if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) |
49 | #if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) |
46 | #define ISFINITE(x) isfinite (x) |
50 | #define ISFINITE(x) isfinite (x) |
Line 54... | Line 58... | ||
54 | * @Short_Description: Font face at particular size and options |
58 | * @Short_Description: Font face at particular size and options |
55 | * @See_Also: #cairo_font_face_t, #cairo_matrix_t, #cairo_font_options_t |
59 | * @See_Also: #cairo_font_face_t, #cairo_matrix_t, #cairo_font_options_t |
56 | * |
60 | * |
57 | * #cairo_scaled_font_t represents a realization of a font face at a particular |
61 | * #cairo_scaled_font_t represents a realization of a font face at a particular |
58 | * size and transformation and a certain set of font options. |
62 | * size and transformation and a certain set of font options. |
59 | */ |
63 | **/ |
- | 64 | ||
- | 65 | static uint32_t |
|
- | 66 | _cairo_scaled_font_compute_hash (cairo_scaled_font_t *scaled_font); |
|
Line 60... | Line 67... | ||
60 | 67 | ||
61 | /* Global Glyph Cache |
68 | /* Global Glyph Cache |
62 | * |
69 | * |
63 | * We maintain a global pool of glyphs split between all active fonts. This |
70 | * We maintain a global pool of glyphs split between all active fonts. This |
Line 195... | Line 202... | ||
195 | 202 | ||
196 | static void |
203 | static void |
197 | _cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, |
204 | _cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, |
198 | cairo_scaled_glyph_t *scaled_glyph) |
205 | cairo_scaled_glyph_t *scaled_glyph) |
- | 206 | { |
|
- | 207 | while (! cairo_list_is_empty (&scaled_glyph->dev_privates)) { |
|
199 | { |
208 | cairo_scaled_glyph_private_t *private = |
- | 209 | cairo_list_first_entry (&scaled_glyph->dev_privates, |
|
- | 210 | cairo_scaled_glyph_private_t, |
|
- | 211 | link); |
|
- | 212 | private->destroy (private, scaled_glyph, scaled_font); |
|
Line 200... | Line -... | ||
200 | const cairo_surface_backend_t *surface_backend = scaled_font->surface_backend; |
- | |
201 | 213 | } |
|
Line 202... | Line 214... | ||
202 | if (surface_backend != NULL && surface_backend->scaled_glyph_fini != NULL) |
214 | |
203 | surface_backend->scaled_glyph_fini (scaled_glyph, scaled_font); |
215 | _cairo_image_scaled_glyph_fini (scaled_font, scaled_glyph); |
Line 204... | Line 216... | ||
204 | 216 | ||
Line 239... | Line 251... | ||
239 | CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */ |
251 | CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */ |
240 | NULL, /* glyphs */ |
252 | NULL, /* glyphs */ |
241 | { NULL, NULL }, /* pages */ |
253 | { NULL, NULL }, /* pages */ |
242 | FALSE, /* cache_frozen */ |
254 | FALSE, /* cache_frozen */ |
243 | FALSE, /* global_cache_frozen */ |
255 | FALSE, /* global_cache_frozen */ |
244 | NULL, /* surface_backend */ |
- | |
245 | NULL, /* surface_private */ |
256 | { NULL, NULL }, /* privates */ |
246 | NULL /* backend */ |
257 | NULL /* backend */ |
247 | }; |
258 | }; |
Line 248... | Line 259... | ||
248 | 259 | ||
249 | /** |
260 | /** |
Line 307... | Line 318... | ||
307 | * Checks whether an error has previously occurred for this |
318 | * Checks whether an error has previously occurred for this |
308 | * scaled_font. |
319 | * scaled_font. |
309 | * |
320 | * |
310 | * Return value: %CAIRO_STATUS_SUCCESS or another error such as |
321 | * Return value: %CAIRO_STATUS_SUCCESS or another error such as |
311 | * %CAIRO_STATUS_NO_MEMORY. |
322 | * %CAIRO_STATUS_NO_MEMORY. |
- | 323 | * |
|
- | 324 | * Since: 1.0 |
|
312 | **/ |
325 | **/ |
313 | cairo_status_t |
326 | cairo_status_t |
314 | cairo_scaled_font_status (cairo_scaled_font_t *scaled_font) |
327 | cairo_scaled_font_status (cairo_scaled_font_t *scaled_font) |
315 | { |
328 | { |
316 | return scaled_font->status; |
329 | return scaled_font->status; |
Line 434... | Line 447... | ||
434 | cairo_scaled_font_map = NULL; |
447 | cairo_scaled_font_map = NULL; |
Line 435... | Line 448... | ||
435 | 448 | ||
436 | CLEANUP_MUTEX_LOCK: |
449 | CLEANUP_MUTEX_LOCK: |
437 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); |
450 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); |
- | 451 | } |
|
438 | } |
452 | |
439 | static void |
453 | static void |
- | 454 | _cairo_scaled_glyph_page_destroy (cairo_scaled_font_t *scaled_font, |
|
440 | _cairo_scaled_glyph_page_destroy (void *closure) |
455 | cairo_scaled_glyph_page_t *page) |
441 | { |
- | |
442 | cairo_scaled_glyph_page_t *page = closure; |
- | |
443 | cairo_scaled_font_t *scaled_font; |
456 | { |
Line -... | Line 457... | ||
- | 457 | unsigned int n; |
|
444 | unsigned int n; |
458 | |
- | 459 | assert (!scaled_font->cache_frozen); |
|
445 | 460 | assert (!scaled_font->global_cache_frozen); |
|
446 | scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash; |
461 | |
447 | for (n = 0; n < page->num_glyphs; n++) { |
462 | for (n = 0; n < page->num_glyphs; n++) { |
448 | _cairo_hash_table_remove (scaled_font->glyphs, |
463 | _cairo_hash_table_remove (scaled_font->glyphs, |
449 | &page->glyphs[n].hash_entry); |
464 | &page->glyphs[n].hash_entry); |
Line 450... | Line 465... | ||
450 | _cairo_scaled_glyph_fini (scaled_font, &page->glyphs[n]); |
465 | _cairo_scaled_glyph_fini (scaled_font, &page->glyphs[n]); |
451 | } |
- | |
452 | 466 | } |
|
453 | cairo_list_del (&page->link); |
467 | |
Line -... | Line 468... | ||
- | 468 | cairo_list_del (&page->link); |
|
- | 469 | free (page); |
|
- | 470 | } |
|
- | 471 | ||
- | 472 | static void |
|
- | 473 | _cairo_scaled_glyph_page_pluck (void *closure) |
|
- | 474 | { |
|
- | 475 | cairo_scaled_glyph_page_t *page = closure; |
|
- | 476 | cairo_scaled_font_t *scaled_font; |
|
- | 477 | ||
- | 478 | assert (! cairo_list_is_empty (&page->link)); |
|
- | 479 | ||
- | 480 | scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash; |
|
- | 481 | ||
- | 482 | CAIRO_MUTEX_LOCK (scaled_font->mutex); |
|
454 | 483 | _cairo_scaled_glyph_page_destroy (scaled_font, page); |
|
455 | free (page); |
484 | CAIRO_MUTEX_UNLOCK (scaled_font->mutex); |
456 | } |
485 | } |
457 | 486 | ||
458 | /* If a scaled font wants to unlock the font map while still being |
487 | /* If a scaled font wants to unlock the font map while still being |
Line 497... | Line 526... | ||
497 | if (unlikely (status)) |
526 | if (unlikely (status)) |
498 | goto FREE_PLACEHOLDER; |
527 | goto FREE_PLACEHOLDER; |
Line 499... | Line 528... | ||
499 | 528 | ||
Line -... | Line 529... | ||
- | 529 | placeholder_scaled_font->placeholder = TRUE; |
|
- | 530 | ||
500 | placeholder_scaled_font->placeholder = TRUE; |
531 | placeholder_scaled_font->hash_entry.hash |
501 | 532 | = _cairo_scaled_font_compute_hash (placeholder_scaled_font); |
|
502 | status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table, |
533 | status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table, |
503 | &placeholder_scaled_font->hash_entry); |
534 | &placeholder_scaled_font->hash_entry); |
Line 522... | Line 553... | ||
522 | { |
553 | { |
523 | cairo_scaled_font_t *placeholder_scaled_font; |
554 | cairo_scaled_font_t *placeholder_scaled_font; |
Line 524... | Line 555... | ||
524 | 555 | ||
Line -... | Line 556... | ||
- | 556 | CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); |
|
- | 557 | ||
- | 558 | /* temporary hash value to match the placeholder */ |
|
525 | CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); |
559 | scaled_font->hash_entry.hash |
526 | 560 | = _cairo_scaled_font_compute_hash (scaled_font); |
|
527 | placeholder_scaled_font = |
561 | placeholder_scaled_font = |
528 | _cairo_hash_table_lookup (cairo_scaled_font_map->hash_table, |
562 | _cairo_hash_table_lookup (cairo_scaled_font_map->hash_table, |
529 | &scaled_font->hash_entry); |
563 | &scaled_font->hash_entry); |
Line 593... | Line 627... | ||
593 | hash ^= hash >> 17; |
627 | hash ^= hash >> 17; |
594 | hash += hash << 5; |
628 | hash += hash << 5; |
595 | return hash; |
629 | return hash; |
596 | } |
630 | } |
Line -... | Line 631... | ||
- | 631 | ||
- | 632 | static uint32_t |
|
- | 633 | _cairo_scaled_font_compute_hash (cairo_scaled_font_t *scaled_font) |
|
- | 634 | { |
|
- | 635 | uint32_t hash = FNV1_32_INIT; |
|
- | 636 | ||
- | 637 | /* We do a bytewise hash on the font matrices */ |
|
- | 638 | hash = _hash_matrix_fnv (&scaled_font->font_matrix, hash); |
|
- | 639 | hash = _hash_matrix_fnv (&scaled_font->ctm, hash); |
|
- | 640 | hash = _hash_mix_bits (hash); |
|
- | 641 | ||
- | 642 | hash ^= (unsigned long) scaled_font->original_font_face; |
|
- | 643 | hash ^= cairo_font_options_hash (&scaled_font->options); |
|
- | 644 | ||
- | 645 | /* final mixing of bits */ |
|
- | 646 | hash = _hash_mix_bits (hash); |
|
- | 647 | assert (hash != ZOMBIE); |
|
- | 648 | ||
- | 649 | return hash; |
|
- | 650 | } |
|
597 | 651 | ||
598 | static void |
652 | static void |
599 | _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, |
653 | _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, |
600 | cairo_font_face_t *font_face, |
654 | cairo_font_face_t *font_face, |
601 | const cairo_matrix_t *font_matrix, |
655 | const cairo_matrix_t *font_matrix, |
602 | const cairo_matrix_t *ctm, |
656 | const cairo_matrix_t *ctm, |
603 | const cairo_font_options_t *options) |
657 | const cairo_font_options_t *options) |
604 | { |
- | |
605 | uint32_t hash = FNV1_32_INIT; |
- | |
606 | 658 | { |
|
607 | scaled_font->status = CAIRO_STATUS_SUCCESS; |
659 | scaled_font->status = CAIRO_STATUS_SUCCESS; |
608 | scaled_font->placeholder = FALSE; |
660 | scaled_font->placeholder = FALSE; |
- | 661 | scaled_font->font_face = font_face; |
|
609 | scaled_font->font_face = font_face; |
662 | scaled_font->original_font_face = font_face; |
610 | scaled_font->font_matrix = *font_matrix; |
663 | scaled_font->font_matrix = *font_matrix; |
611 | scaled_font->ctm = *ctm; |
664 | scaled_font->ctm = *ctm; |
612 | /* ignore translation values in the ctm */ |
665 | /* ignore translation values in the ctm */ |
613 | scaled_font->ctm.x0 = 0.; |
666 | scaled_font->ctm.x0 = 0.; |
614 | scaled_font->ctm.y0 = 0.; |
667 | scaled_font->ctm.y0 = 0.; |
Line 615... | Line -... | ||
615 | _cairo_font_options_init_copy (&scaled_font->options, options); |
- | |
616 | - | ||
617 | /* We do a bytewise hash on the font matrices */ |
- | |
618 | hash = _hash_matrix_fnv (&scaled_font->font_matrix, hash); |
668 | _cairo_font_options_init_copy (&scaled_font->options, options); |
619 | hash = _hash_matrix_fnv (&scaled_font->ctm, hash); |
- | |
620 | hash = _hash_mix_bits (hash); |
- | |
621 | 669 | ||
622 | hash ^= (unsigned long) scaled_font->font_face; |
- | |
623 | hash ^= cairo_font_options_hash (&scaled_font->options); |
- | |
624 | - | ||
625 | /* final mixing of bits */ |
- | |
626 | hash = _hash_mix_bits (hash); |
- | |
627 | - | ||
628 | assert (hash != ZOMBIE); |
670 | scaled_font->hash_entry.hash = |
Line 629... | Line 671... | ||
629 | scaled_font->hash_entry.hash = hash; |
671 | _cairo_scaled_font_compute_hash (scaled_font); |
630 | } |
672 | } |
631 | 673 | ||
632 | static cairo_bool_t |
674 | static cairo_bool_t |
633 | _cairo_scaled_font_keys_equal (const void *abstract_key_a, |
675 | _cairo_scaled_font_keys_equal (const void *abstract_key_a, |
634 | const void *abstract_key_b) |
676 | const void *abstract_key_b) |
Line 635... | Line -... | ||
635 | { |
- | |
636 | const cairo_scaled_font_t *key_a = abstract_key_a; |
- | |
637 | const cairo_scaled_font_t *key_b = abstract_key_b; |
- | |
638 | 677 | { |
|
639 | if (key_a->hash_entry.hash != key_b->hash_entry.hash) |
678 | const cairo_scaled_font_t *key_a = abstract_key_a; |
640 | return FALSE; |
679 | const cairo_scaled_font_t *key_b = abstract_key_b; |
641 | 680 | ||
642 | return key_a->font_face == key_b->font_face && |
681 | return key_a->original_font_face == key_b->original_font_face && |
643 | memcmp ((unsigned char *)(&key_a->font_matrix.xx), |
682 | memcmp ((unsigned char *)(&key_a->font_matrix.xx), |
Line 664... | Line 703... | ||
664 | (unsigned char *)(&ctm->xx), |
703 | (unsigned char *)(&ctm->xx), |
665 | sizeof(cairo_matrix_t)) == 0 && |
704 | sizeof(cairo_matrix_t)) == 0 && |
666 | cairo_font_options_equal (&scaled_font->options, options); |
705 | cairo_font_options_equal (&scaled_font->options, options); |
667 | } |
706 | } |
Line 668... | Line -... | ||
668 | - | ||
669 | static cairo_bool_t |
- | |
670 | _cairo_scaled_glyphs_equal (const void *abstract_a, const void *abstract_b) |
- | |
671 | { |
- | |
672 | const cairo_scaled_glyph_t *a = abstract_a; |
- | |
673 | const cairo_scaled_glyph_t *b = abstract_b; |
- | |
674 | - | ||
675 | return a->hash_entry.hash == b->hash_entry.hash; |
- | |
676 | } |
- | |
677 | 707 | ||
678 | /* |
708 | /* |
679 | * Basic #cairo_scaled_font_t object management |
709 | * Basic #cairo_scaled_font_t object management |
Line 680... | Line 710... | ||
680 | */ |
710 | */ |
Line 691... | Line 721... | ||
691 | 721 | ||
692 | status = cairo_font_options_status ((cairo_font_options_t *) options); |
722 | status = cairo_font_options_status ((cairo_font_options_t *) options); |
693 | if (unlikely (status)) |
723 | if (unlikely (status)) |
Line -... | Line 724... | ||
- | 724 | return status; |
|
- | 725 | ||
- | 726 | scaled_font->status = CAIRO_STATUS_SUCCESS; |
|
694 | return status; |
727 | scaled_font->placeholder = FALSE; |
695 | 728 | scaled_font->font_face = font_face; |
|
- | 729 | scaled_font->original_font_face = font_face; |
|
- | 730 | scaled_font->font_matrix = *font_matrix; |
|
- | 731 | scaled_font->ctm = *ctm; |
|
- | 732 | /* ignore translation values in the ctm */ |
|
- | 733 | scaled_font->ctm.x0 = 0.; |
|
Line 696... | Line 734... | ||
696 | _cairo_scaled_font_init_key (scaled_font, font_face, |
734 | scaled_font->ctm.y0 = 0.; |
697 | font_matrix, ctm, options); |
735 | _cairo_font_options_init_copy (&scaled_font->options, options); |
698 | 736 | ||
Line 721... | Line 759... | ||
721 | -scaled_font->scale.y0); |
759 | -scaled_font->scale.y0); |
722 | } else |
760 | } else |
723 | return status; |
761 | return status; |
724 | } |
762 | } |
Line 725... | Line 763... | ||
725 | 763 | ||
726 | scaled_font->glyphs = _cairo_hash_table_create (_cairo_scaled_glyphs_equal); |
764 | scaled_font->glyphs = _cairo_hash_table_create (NULL); |
727 | if (unlikely (scaled_font->glyphs == NULL)) |
765 | if (unlikely (scaled_font->glyphs == NULL)) |
Line 728... | Line 766... | ||
728 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
766 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
729 | 767 | ||
Line 741... | Line 779... | ||
741 | cairo_font_face_reference (font_face); |
779 | cairo_font_face_reference (font_face); |
742 | scaled_font->original_font_face = NULL; |
780 | scaled_font->original_font_face = NULL; |
Line 743... | Line 781... | ||
743 | 781 | ||
Line 744... | Line -... | ||
744 | CAIRO_MUTEX_INIT (scaled_font->mutex); |
- | |
745 | 782 | CAIRO_MUTEX_INIT (scaled_font->mutex); |
|
Line 746... | Line 783... | ||
746 | scaled_font->surface_backend = NULL; |
783 | |
747 | scaled_font->surface_private = NULL; |
784 | cairo_list_init (&scaled_font->dev_privates); |
Line 748... | Line 785... | ||
748 | 785 | ||
Line 763... | Line 800... | ||
763 | } |
800 | } |
Line 764... | Line 801... | ||
764 | 801 | ||
765 | void |
802 | void |
766 | _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font) |
803 | _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font) |
767 | { |
804 | { |
Line 768... | Line 805... | ||
768 | scaled_font->cache_frozen = FALSE; |
805 | assert (scaled_font->cache_frozen); |
769 | 806 | ||
770 | if (scaled_font->global_cache_frozen) { |
807 | if (scaled_font->global_cache_frozen) { |
771 | CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex); |
808 | CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex); |
772 | _cairo_cache_thaw (&cairo_scaled_glyph_page_cache); |
- | |
773 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex); |
809 | _cairo_cache_thaw (&cairo_scaled_glyph_page_cache); |
774 | 810 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex); |
|
Line -... | Line 811... | ||
- | 811 | scaled_font->global_cache_frozen = FALSE; |
|
775 | scaled_font->global_cache_frozen = FALSE; |
812 | } |
776 | } |
813 | |
Line 777... | Line 814... | ||
777 | 814 | scaled_font->cache_frozen = FALSE; |
|
778 | CAIRO_MUTEX_UNLOCK (scaled_font->mutex); |
815 | CAIRO_MUTEX_UNLOCK (scaled_font->mutex); |
779 | } |
816 | } |
- | 817 | ||
780 | 818 | void |
|
781 | void |
- | |
- | 819 | _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font) |
|
782 | _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font) |
820 | { |
783 | { |
821 | CAIRO_MUTEX_LOCK (scaled_font->mutex); |
784 | assert (! scaled_font->cache_frozen); |
822 | assert (! scaled_font->cache_frozen); |
785 | 823 | assert (! scaled_font->global_cache_frozen); |
|
786 | CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex); |
824 | CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex); |
- | 825 | while (! cairo_list_is_empty (&scaled_font->glyph_pages)) { |
|
- | 826 | cairo_scaled_glyph_page_t *page = |
|
- | 827 | cairo_list_first_entry (&scaled_font->glyph_pages, |
|
- | 828 | cairo_scaled_glyph_page_t, |
|
787 | while (! cairo_list_is_empty (&scaled_font->glyph_pages)) { |
829 | link); |
- | 830 | ||
- | 831 | cairo_scaled_glyph_page_cache.size -= page->cache_entry.size; |
|
788 | _cairo_cache_remove (&cairo_scaled_glyph_page_cache, |
832 | _cairo_hash_table_remove (cairo_scaled_glyph_page_cache.hash_table, |
789 | &cairo_list_first_entry (&scaled_font->glyph_pages, |
833 | (cairo_hash_entry_t *) &page->cache_entry); |
- | 834 | ||
790 | cairo_scaled_glyph_page_t, |
835 | _cairo_scaled_glyph_page_destroy (scaled_font, page); |
Line 791... | Line 836... | ||
791 | link)->cache_entry); |
836 | } |
792 | } |
837 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex); |
793 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex); |
838 | CAIRO_MUTEX_UNLOCK (scaled_font->mutex); |
Line 823... | Line 868... | ||
823 | } |
868 | } |
Line 824... | Line 869... | ||
824 | 869 | ||
825 | static void |
870 | static void |
826 | _cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font) |
871 | _cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font) |
- | 872 | { |
|
- | 873 | assert (! scaled_font->cache_frozen); |
|
827 | { |
874 | assert (! scaled_font->global_cache_frozen); |
Line 828... | Line 875... | ||
828 | scaled_font->finished = TRUE; |
875 | scaled_font->finished = TRUE; |
829 | 876 | ||
Line 830... | Line 877... | ||
830 | _cairo_scaled_font_reset_cache (scaled_font); |
877 | _cairo_scaled_font_reset_cache (scaled_font); |
831 | _cairo_hash_table_destroy (scaled_font->glyphs); |
878 | _cairo_hash_table_destroy (scaled_font->glyphs); |
Line 832... | Line 879... | ||
832 | 879 | ||
Line -... | Line 880... | ||
- | 880 | cairo_font_face_destroy (scaled_font->font_face); |
|
833 | cairo_font_face_destroy (scaled_font->font_face); |
881 | cairo_font_face_destroy (scaled_font->original_font_face); |
834 | cairo_font_face_destroy (scaled_font->original_font_face); |
882 | |
- | 883 | CAIRO_MUTEX_FINI (scaled_font->mutex); |
|
- | 884 | ||
835 | 885 | while (! cairo_list_is_empty (&scaled_font->dev_privates)) { |
|
- | 886 | cairo_scaled_font_private_t *private = |
|
Line 836... | Line 887... | ||
836 | CAIRO_MUTEX_FINI (scaled_font->mutex); |
887 | cairo_list_first_entry (&scaled_font->dev_privates, |
837 | 888 | cairo_scaled_font_private_t, |
|
Line 838... | Line 889... | ||
838 | if (scaled_font->surface_backend != NULL && |
889 | link); |
839 | scaled_font->surface_backend->scaled_font_fini != NULL) |
890 | private->destroy (private, scaled_font); |
Line 840... | Line -... | ||
840 | scaled_font->surface_backend->scaled_font_fini (scaled_font); |
- | |
841 | - | ||
842 | if (scaled_font->backend != NULL && scaled_font->backend->fini != NULL) |
- | |
843 | scaled_font->backend->fini (scaled_font); |
- | |
844 | - | ||
845 | _cairo_user_data_array_fini (&scaled_font->user_data); |
- | |
846 | } |
- | |
847 | - | ||
848 | /* XXX: allow multiple backends to share the font */ |
- | |
849 | void |
- | |
850 | _cairo_scaled_font_revoke_ownership (cairo_scaled_font_t *scaled_font) |
- | |
851 | { |
- | |
852 | if (scaled_font->surface_backend == NULL) |
- | |
853 | return; |
- | |
854 | - | ||
855 | _cairo_scaled_font_reset_cache (scaled_font); |
- | |
856 | 891 | } |
|
857 | if (scaled_font->surface_backend->scaled_font_fini != NULL) |
892 | |
858 | scaled_font->surface_backend->scaled_font_fini (scaled_font); |
893 | if (scaled_font->backend != NULL && scaled_font->backend->fini != NULL) |
859 | 894 | scaled_font->backend->fini (scaled_font); |
|
860 | scaled_font->surface_backend = NULL; |
895 | |
861 | scaled_font->surface_private = NULL; |
896 | _cairo_user_data_array_fini (&scaled_font->user_data); |
862 | } |
897 | } |
863 | 898 | ||
864 | void |
899 | void |
Line -... | Line 900... | ||
- | 900 | _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) |
|
- | 901 | { |
|
- | 902 | /* Release the lock to avoid the possibility of a recursive |
|
- | 903 | * deadlock when the scaled font destroy closure gets called. */ |
|
- | 904 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); |
|
- | 905 | _cairo_scaled_font_fini_internal (scaled_font); |
|
- | 906 | CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); |
|
- | 907 | } |
|
- | 908 | ||
- | 909 | void |
|
- | 910 | _cairo_scaled_font_attach_private (cairo_scaled_font_t *scaled_font, |
|
- | 911 | cairo_scaled_font_private_t *private, |
|
- | 912 | const void *key, |
|
- | 913 | void (*destroy) (cairo_scaled_font_private_t *, |
|
- | 914 | cairo_scaled_font_t *)) |
|
- | 915 | { |
|
- | 916 | private->key = key; |
|
- | 917 | private->destroy = destroy; |
|
- | 918 | cairo_list_add (&private->link, &scaled_font->dev_privates); |
|
- | 919 | } |
|
- | 920 | ||
- | 921 | cairo_scaled_font_private_t * |
|
- | 922 | _cairo_scaled_font_find_private (cairo_scaled_font_t *scaled_font, |
|
- | 923 | const void *key) |
|
- | 924 | { |
|
- | 925 | cairo_scaled_font_private_t *priv; |
|
- | 926 | ||
- | 927 | cairo_list_foreach_entry (priv, cairo_scaled_font_private_t, |
|
- | 928 | &scaled_font->dev_privates, link) |
|
- | 929 | { |
|
- | 930 | if (priv->key == key) { |
|
- | 931 | if (priv->link.prev != &scaled_font->dev_privates) |
|
- | 932 | cairo_list_move (&priv->link, &scaled_font->dev_privates); |
|
- | 933 | return priv; |
|
- | 934 | } |
|
- | 935 | } |
|
- | 936 | ||
- | 937 | return NULL; |
|
- | 938 | } |
|
- | 939 | ||
- | 940 | void |
|
- | 941 | _cairo_scaled_glyph_attach_private (cairo_scaled_glyph_t *scaled_glyph, |
|
- | 942 | cairo_scaled_glyph_private_t *private, |
|
- | 943 | const void *key, |
|
- | 944 | void (*destroy) (cairo_scaled_glyph_private_t *, |
|
- | 945 | cairo_scaled_glyph_t *, |
|
- | 946 | cairo_scaled_font_t *)) |
|
- | 947 | { |
|
- | 948 | private->key = key; |
|
- | 949 | private->destroy = destroy; |
|
- | 950 | cairo_list_add (&private->link, &scaled_glyph->dev_privates); |
|
- | 951 | } |
|
- | 952 | ||
- | 953 | cairo_scaled_glyph_private_t * |
|
- | 954 | _cairo_scaled_glyph_find_private (cairo_scaled_glyph_t *scaled_glyph, |
|
- | 955 | const void *key) |
|
- | 956 | { |
|
- | 957 | cairo_scaled_glyph_private_t *priv; |
|
- | 958 | ||
- | 959 | cairo_list_foreach_entry (priv, cairo_scaled_glyph_private_t, |
|
- | 960 | &scaled_glyph->dev_privates, link) |
|
- | 961 | { |
|
- | 962 | if (priv->key == key) { |
|
865 | _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) |
963 | if (priv->link.prev != &scaled_glyph->dev_privates) |
866 | { |
964 | cairo_list_move (&priv->link, &scaled_glyph->dev_privates); |
867 | /* Release the lock to avoid the possibility of a recursive |
965 | return priv; |
868 | * deadlock when the scaled font destroy closure gets called. */ |
966 | } |
869 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); |
967 | } |
Line 888... | Line 986... | ||
888 | * describe the size of the font and the environment in which it will |
986 | * describe the size of the font and the environment in which it will |
889 | * be used. |
987 | * be used. |
890 | * |
988 | * |
891 | * Return value: a newly created #cairo_scaled_font_t. Destroy with |
989 | * Return value: a newly created #cairo_scaled_font_t. Destroy with |
892 | * cairo_scaled_font_destroy() |
990 | * cairo_scaled_font_destroy() |
- | 991 | * |
|
- | 992 | * Since: 1.0 |
|
893 | **/ |
993 | **/ |
894 | cairo_scaled_font_t * |
994 | cairo_scaled_font_t * |
895 | cairo_scaled_font_create (cairo_font_face_t *font_face, |
995 | cairo_scaled_font_create (cairo_font_face_t *font_face, |
896 | const cairo_matrix_t *font_matrix, |
996 | const cairo_matrix_t *font_matrix, |
897 | const cairo_matrix_t *ctm, |
997 | const cairo_matrix_t *ctm, |
Line 948... | Line 1048... | ||
948 | _cairo_hash_table_remove (font_map->hash_table, |
1048 | _cairo_hash_table_remove (font_map->hash_table, |
949 | &scaled_font->hash_entry); |
1049 | &scaled_font->hash_entry); |
950 | scaled_font->hash_entry.hash = ZOMBIE; |
1050 | scaled_font->hash_entry.hash = ZOMBIE; |
951 | dead = scaled_font; |
1051 | dead = scaled_font; |
952 | font_map->mru_scaled_font = NULL; |
1052 | font_map->mru_scaled_font = NULL; |
953 | - | ||
954 | if (font_face->backend->get_implementation != NULL) { |
- | |
955 | font_face = font_face->backend->get_implementation (font_face, |
- | |
956 | font_matrix, |
- | |
957 | ctm, |
- | |
958 | options); |
- | |
959 | if (unlikely (font_face->status)) { |
- | |
960 | _cairo_scaled_font_map_unlock (); |
- | |
961 | cairo_scaled_font_destroy (scaled_font); |
- | |
962 | return _cairo_scaled_font_create_in_error (font_face->status); |
- | |
963 | } |
- | |
964 | } |
- | |
965 | - | ||
966 | _cairo_scaled_font_init_key (&key, font_face, |
- | |
967 | font_matrix, ctm, options); |
- | |
968 | } |
- | |
969 | else |
- | |
970 | { |
- | |
971 | if (font_face->backend->get_implementation != NULL) { |
- | |
972 | font_face = font_face->backend->get_implementation (font_face, |
- | |
973 | font_matrix, |
- | |
974 | ctm, |
- | |
975 | options); |
- | |
976 | if (unlikely (font_face->status)) { |
- | |
977 | _cairo_scaled_font_map_unlock (); |
- | |
978 | return _cairo_scaled_font_create_in_error (font_face->status); |
- | |
979 | } |
- | |
980 | } |
1053 | } |
Line 981... | Line 1054... | ||
981 | 1054 | ||
982 | _cairo_scaled_font_init_key (&key, font_face, |
- | |
Line 983... | Line 1055... | ||
983 | font_matrix, ctm, options); |
1055 | _cairo_scaled_font_init_key (&key, font_face, font_matrix, ctm, options); |
984 | 1056 | ||
985 | while ((scaled_font = _cairo_hash_table_lookup (font_map->hash_table, |
1057 | while ((scaled_font = _cairo_hash_table_lookup (font_map->hash_table, |
986 | &key.hash_entry))) |
1058 | &key.hash_entry))) |
Line 991... | Line 1063... | ||
991 | /* If the scaled font is being created (happens for user-font), |
1063 | /* If the scaled font is being created (happens for user-font), |
992 | * just wait until it's done, then retry */ |
1064 | * just wait until it's done, then retry */ |
993 | _cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font); |
1065 | _cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font); |
994 | } |
1066 | } |
Line 995... | Line -... | ||
995 | - | ||
996 | /* Return existing scaled_font if it exists in the hash table. */ |
1067 | |
997 | if (scaled_font != NULL) { |
1068 | if (scaled_font != NULL) { |
998 | /* If the original reference count is 0, then this font must have |
1069 | /* If the original reference count is 0, then this font must have |
999 | * been found in font_map->holdovers, (which means this caching is |
1070 | * been found in font_map->holdovers, (which means this caching is |
1000 | * actually working). So now we remove it from the holdovers |
1071 | * actually working). So now we remove it from the holdovers |
Line 1045... | Line 1116... | ||
1045 | /* the font has been put into an error status - abandon the cache */ |
1116 | /* the font has been put into an error status - abandon the cache */ |
1046 | _cairo_hash_table_remove (font_map->hash_table, |
1117 | _cairo_hash_table_remove (font_map->hash_table, |
1047 | &scaled_font->hash_entry); |
1118 | &scaled_font->hash_entry); |
1048 | scaled_font->hash_entry.hash = ZOMBIE; |
1119 | scaled_font->hash_entry.hash = ZOMBIE; |
1049 | } |
1120 | } |
1050 | } |
1121 | |
Line 1051... | Line 1122... | ||
1051 | 1122 | ||
- | 1123 | /* Otherwise create it and insert it into the hash table. */ |
|
- | 1124 | if (font_face->backend->get_implementation != NULL) { |
|
- | 1125 | font_face = font_face->backend->get_implementation (font_face, |
|
- | 1126 | font_matrix, |
|
- | 1127 | ctm, |
|
- | 1128 | options); |
|
- | 1129 | if (unlikely (font_face->status)) { |
|
- | 1130 | _cairo_scaled_font_map_unlock (); |
|
- | 1131 | return _cairo_scaled_font_create_in_error (font_face->status); |
|
- | 1132 | } |
|
- | 1133 | } |
|
1052 | /* Otherwise create it and insert it into the hash table. */ |
1134 | |
1053 | status = font_face->backend->scaled_font_create (font_face, font_matrix, |
1135 | status = font_face->backend->scaled_font_create (font_face, font_matrix, |
1054 | ctm, options, &scaled_font); |
1136 | ctm, options, &scaled_font); |
1055 | /* Did we leave the backend in an error state? */ |
1137 | /* Did we leave the backend in an error state? */ |
1056 | if (unlikely (status)) { |
1138 | if (unlikely (status)) { |
Line 1079... | Line 1161... | ||
1079 | /* Our caching above is defeated if the backend switches fonts on us - |
1161 | /* Our caching above is defeated if the backend switches fonts on us - |
1080 | * e.g. old incarnations of toy-font-face and lazily resolved |
1162 | * e.g. old incarnations of toy-font-face and lazily resolved |
1081 | * ft-font-faces |
1163 | * ft-font-faces |
1082 | */ |
1164 | */ |
1083 | assert (scaled_font->font_face == font_face); |
1165 | assert (scaled_font->font_face == font_face); |
- | 1166 | assert (! scaled_font->cache_frozen); |
|
- | 1167 | assert (! scaled_font->global_cache_frozen); |
|
Line 1084... | Line 1168... | ||
1084 | 1168 | ||
1085 | scaled_font->original_font_face = |
1169 | scaled_font->original_font_face = |
Line -... | Line 1170... | ||
- | 1170 | cairo_font_face_reference (original_font_face); |
|
- | 1171 | ||
1086 | cairo_font_face_reference (original_font_face); |
1172 | scaled_font->hash_entry.hash = _cairo_scaled_font_compute_hash(scaled_font); |
1087 | 1173 | ||
1088 | status = _cairo_hash_table_insert (font_map->hash_table, |
1174 | status = _cairo_hash_table_insert (font_map->hash_table, |
1089 | &scaled_font->hash_entry); |
1175 | &scaled_font->hash_entry); |
1090 | if (likely (status == CAIRO_STATUS_SUCCESS)) { |
1176 | if (likely (status == CAIRO_STATUS_SUCCESS)) { |
Line 1155... | Line 1241... | ||
1155 | CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex); |
1241 | CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex); |
1156 | for (status = CAIRO_STATUS_SUCCESS; |
1242 | for (status = CAIRO_STATUS_SUCCESS; |
1157 | status <= CAIRO_STATUS_LAST_STATUS; |
1243 | status <= CAIRO_STATUS_LAST_STATUS; |
1158 | status++) |
1244 | status++) |
1159 | { |
1245 | { |
1160 | if (_cairo_scaled_font_nil_objects[status] != NULL) { |
- | |
1161 | free (_cairo_scaled_font_nil_objects[status]); |
1246 | free (_cairo_scaled_font_nil_objects[status]); |
1162 | _cairo_scaled_font_nil_objects[status] = NULL; |
1247 | _cairo_scaled_font_nil_objects[status] = NULL; |
1163 | } |
1248 | } |
1164 | } |
- | |
1165 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex); |
1249 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex); |
Line 1166... | Line 1250... | ||
1166 | 1250 | ||
1167 | CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex); |
1251 | CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex); |
1168 | if (cairo_scaled_glyph_page_cache.hash_table != NULL) { |
1252 | if (cairo_scaled_glyph_page_cache.hash_table != NULL) { |
Line 1183... | Line 1267... | ||
1183 | * |
1267 | * |
1184 | * The number of references to a #cairo_scaled_font_t can be get using |
1268 | * The number of references to a #cairo_scaled_font_t can be get using |
1185 | * cairo_scaled_font_get_reference_count(). |
1269 | * cairo_scaled_font_get_reference_count(). |
1186 | * |
1270 | * |
1187 | * Returns: the referenced #cairo_scaled_font_t |
1271 | * Returns: the referenced #cairo_scaled_font_t |
- | 1272 | * |
|
- | 1273 | * Since: 1.0 |
|
1188 | **/ |
1274 | **/ |
1189 | cairo_scaled_font_t * |
1275 | cairo_scaled_font_t * |
1190 | cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) |
1276 | cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) |
1191 | { |
1277 | { |
1192 | if (scaled_font == NULL || |
1278 | if (scaled_font == NULL || |
Line 1206... | Line 1292... | ||
1206 | * @scaled_font: a #cairo_scaled_font_t |
1292 | * @scaled_font: a #cairo_scaled_font_t |
1207 | * |
1293 | * |
1208 | * Decreases the reference count on @font by one. If the result |
1294 | * Decreases the reference count on @font by one. If the result |
1209 | * is zero, then @font and all associated resources are freed. |
1295 | * is zero, then @font and all associated resources are freed. |
1210 | * See cairo_scaled_font_reference(). |
1296 | * See cairo_scaled_font_reference(). |
- | 1297 | * |
|
- | 1298 | * Since: 1.0 |
|
1211 | **/ |
1299 | **/ |
1212 | void |
1300 | void |
1213 | cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) |
1301 | cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) |
1214 | { |
1302 | { |
1215 | cairo_scaled_font_t *lru = NULL; |
1303 | cairo_scaled_font_t *lru = NULL; |
Line 1224... | Line 1312... | ||
1224 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)); |
1312 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)); |
Line 1225... | Line 1313... | ||
1225 | 1313 | ||
1226 | if (! _cairo_reference_count_dec_and_test (&scaled_font->ref_count)) |
1314 | if (! _cairo_reference_count_dec_and_test (&scaled_font->ref_count)) |
Line -... | Line 1315... | ||
- | 1315 | return; |
|
- | 1316 | ||
- | 1317 | assert (! scaled_font->cache_frozen); |
|
1227 | return; |
1318 | assert (! scaled_font->global_cache_frozen); |
1228 | 1319 | ||
Line 1229... | Line 1320... | ||
1229 | font_map = _cairo_scaled_font_map_lock (); |
1320 | font_map = _cairo_scaled_font_map_lock (); |
1230 | assert (font_map != NULL); |
1321 | assert (font_map != NULL); |
Line 1362... | Line 1453... | ||
1362 | * cairo_scaled_font_extents: |
1453 | * cairo_scaled_font_extents: |
1363 | * @scaled_font: a #cairo_scaled_font_t |
1454 | * @scaled_font: a #cairo_scaled_font_t |
1364 | * @extents: a #cairo_font_extents_t which to store the retrieved extents. |
1455 | * @extents: a #cairo_font_extents_t which to store the retrieved extents. |
1365 | * |
1456 | * |
1366 | * Gets the metrics for a #cairo_scaled_font_t. |
1457 | * Gets the metrics for a #cairo_scaled_font_t. |
- | 1458 | * |
|
- | 1459 | * Since: 1.0 |
|
1367 | **/ |
1460 | **/ |
1368 | void |
1461 | void |
1369 | cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, |
1462 | cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, |
1370 | cairo_font_extents_t *extents) |
1463 | cairo_font_extents_t *extents) |
1371 | { |
1464 | { |
Line 1459... | Line 1552... | ||
1459 | * y_advance values indicate the amount by which the current point |
1552 | * y_advance values indicate the amount by which the current point |
1460 | * would be advanced by cairo_show_glyphs(). |
1553 | * would be advanced by cairo_show_glyphs(). |
1461 | * |
1554 | * |
1462 | * Note that whitespace glyphs do not contribute to the size of the |
1555 | * Note that whitespace glyphs do not contribute to the size of the |
1463 | * rectangle (extents.width and extents.height). |
1556 | * rectangle (extents.width and extents.height). |
- | 1557 | * |
|
- | 1558 | * Since: 1.0 |
|
1464 | **/ |
1559 | **/ |
1465 | void |
1560 | void |
1466 | cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, |
1561 | cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, |
1467 | const cairo_glyph_t *glyphs, |
1562 | const cairo_glyph_t *glyphs, |
1468 | int num_glyphs, |
1563 | int num_glyphs, |
Line 1854... | Line 1949... | ||
1854 | cairo_text_cluster_t **clusters, |
1949 | cairo_text_cluster_t **clusters, |
1855 | int *num_clusters, |
1950 | int *num_clusters, |
1856 | cairo_text_cluster_flags_t *cluster_flags) |
1951 | cairo_text_cluster_flags_t *cluster_flags) |
1857 | { |
1952 | { |
1858 | int num_chars = 0; |
1953 | int num_chars = 0; |
1859 | cairo_status_t status; |
1954 | cairo_int_status_t status; |
1860 | cairo_glyph_t *orig_glyphs; |
1955 | cairo_glyph_t *orig_glyphs; |
1861 | cairo_text_cluster_t *orig_clusters; |
1956 | cairo_text_cluster_t *orig_clusters; |
Line 1862... | Line 1957... | ||
1862 | 1957 | ||
1863 | status = scaled_font->status; |
1958 | status = scaled_font->status; |
Line 1937... | Line 2032... | ||
1937 | utf8, utf8_len, |
2032 | utf8, utf8_len, |
1938 | glyphs, num_glyphs, |
2033 | glyphs, num_glyphs, |
1939 | clusters, num_clusters, |
2034 | clusters, num_clusters, |
1940 | cluster_flags); |
2035 | cluster_flags); |
1941 | if (status != CAIRO_INT_STATUS_UNSUPPORTED) { |
2036 | if (status != CAIRO_INT_STATUS_UNSUPPORTED) { |
1942 | if (status == CAIRO_STATUS_SUCCESS) { |
2037 | if (status == CAIRO_INT_STATUS_SUCCESS) { |
1943 | /* The checks here are crude; we only should do them in |
2038 | /* The checks here are crude; we only should do them in |
1944 | * user-font backend, but they don't hurt here. This stuff |
2039 | * user-font backend, but they don't hurt here. This stuff |
1945 | * can be hard to get right. */ |
2040 | * can be hard to get right. */ |
Line 1946... | Line 2041... | ||
1946 | 2041 | ||
Line 2049... | Line 2144... | ||
2049 | cairo_fixed_t left, |
2144 | cairo_fixed_t left, |
2050 | cairo_fixed_t top, |
2145 | cairo_fixed_t top, |
2051 | cairo_fixed_t right, |
2146 | cairo_fixed_t right, |
2052 | cairo_fixed_t bottom) |
2147 | cairo_fixed_t bottom) |
2053 | { |
2148 | { |
- | 2149 | if (left == right || top == bottom) |
|
- | 2150 | return FALSE; |
|
- | 2151 | ||
2054 | return right > extents->p1.x && |
2152 | return right > extents->p1.x && |
2055 | left < extents->p2.x && |
2153 | left < extents->p2.x && |
2056 | bottom > extents->p1.y && |
2154 | bottom > extents->p1.y && |
2057 | top < extents->p2.y; |
2155 | top < extents->p2.y; |
2058 | } |
2156 | } |
Line -... | Line 2157... | ||
- | 2157 | ||
- | 2158 | static cairo_status_t |
|
- | 2159 | _cairo_scaled_font_single_glyph_device_extents (cairo_scaled_font_t *scaled_font, |
|
- | 2160 | const cairo_glyph_t *glyph, |
|
- | 2161 | cairo_rectangle_int_t *extents) |
|
- | 2162 | { |
|
- | 2163 | cairo_scaled_glyph_t *scaled_glyph; |
|
- | 2164 | cairo_status_t status; |
|
- | 2165 | ||
- | 2166 | _cairo_scaled_font_freeze_cache (scaled_font); |
|
- | 2167 | status = _cairo_scaled_glyph_lookup (scaled_font, |
|
- | 2168 | glyph->index, |
|
- | 2169 | CAIRO_SCALED_GLYPH_INFO_METRICS, |
|
- | 2170 | &scaled_glyph); |
|
- | 2171 | if (likely (status == CAIRO_STATUS_SUCCESS)) { |
|
- | 2172 | cairo_bool_t round_xy = _cairo_font_options_get_round_glyph_positions (&scaled_font->options) == CAIRO_ROUND_GLYPH_POS_ON; |
|
- | 2173 | cairo_box_t box; |
|
- | 2174 | cairo_fixed_t v; |
|
- | 2175 | ||
- | 2176 | if (round_xy) |
|
- | 2177 | v = _cairo_fixed_from_int (_cairo_lround (glyph->x)); |
|
- | 2178 | else |
|
- | 2179 | v = _cairo_fixed_from_double (glyph->x); |
|
- | 2180 | box.p1.x = v + scaled_glyph->bbox.p1.x; |
|
- | 2181 | box.p2.x = v + scaled_glyph->bbox.p2.x; |
|
- | 2182 | ||
- | 2183 | if (round_xy) |
|
- | 2184 | v = _cairo_fixed_from_int (_cairo_lround (glyph->y)); |
|
- | 2185 | else |
|
- | 2186 | v = _cairo_fixed_from_double (glyph->y); |
|
- | 2187 | box.p1.y = v + scaled_glyph->bbox.p1.y; |
|
- | 2188 | box.p2.y = v + scaled_glyph->bbox.p2.y; |
|
- | 2189 | ||
- | 2190 | _cairo_box_round_to_rectangle (&box, extents); |
|
- | 2191 | } |
|
- | 2192 | _cairo_scaled_font_thaw_cache (scaled_font); |
|
- | 2193 | return status; |
|
- | 2194 | } |
|
2059 | 2195 | ||
2060 | /* |
2196 | /* |
2061 | * Compute a device-space bounding box for the glyphs. |
2197 | * Compute a device-space bounding box for the glyphs. |
2062 | */ |
2198 | */ |
2063 | cairo_status_t |
2199 | cairo_status_t |
Line 2069... | Line 2205... | ||
2069 | { |
2205 | { |
2070 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
2206 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
2071 | cairo_box_t box = { { INT_MAX, INT_MAX }, { INT_MIN, INT_MIN }}; |
2207 | cairo_box_t box = { { INT_MAX, INT_MAX }, { INT_MIN, INT_MIN }}; |
2072 | cairo_scaled_glyph_t *glyph_cache[64]; |
2208 | cairo_scaled_glyph_t *glyph_cache[64]; |
2073 | cairo_bool_t overlap = overlap_out ? FALSE : TRUE; |
2209 | cairo_bool_t overlap = overlap_out ? FALSE : TRUE; |
- | 2210 | cairo_round_glyph_positions_t round_glyph_positions = _cairo_font_options_get_round_glyph_positions (&scaled_font->options); |
|
2074 | int i; |
2211 | int i; |
Line 2075... | Line 2212... | ||
2075 | 2212 | ||
2076 | if (unlikely (scaled_font->status)) |
2213 | if (unlikely (scaled_font->status)) |
Line -... | Line 2214... | ||
- | 2214 | return scaled_font->status; |
|
- | 2215 | ||
- | 2216 | if (num_glyphs == 1) { |
|
- | 2217 | if (overlap_out) |
|
- | 2218 | *overlap_out = FALSE; |
|
- | 2219 | return _cairo_scaled_font_single_glyph_device_extents (scaled_font, |
|
- | 2220 | glyphs, |
|
- | 2221 | extents); |
|
2077 | return scaled_font->status; |
2222 | } |
Line 2078... | Line 2223... | ||
2078 | 2223 | ||
Line 2079... | Line 2224... | ||
2079 | _cairo_scaled_font_freeze_cache (scaled_font); |
2224 | _cairo_scaled_font_freeze_cache (scaled_font); |
Line 2097... | Line 2242... | ||
2097 | break; |
2242 | break; |
Line 2098... | Line 2243... | ||
2098 | 2243 | ||
2099 | glyph_cache[cache_index] = scaled_glyph; |
2244 | glyph_cache[cache_index] = scaled_glyph; |
Line -... | Line 2245... | ||
- | 2245 | } |
|
- | 2246 | ||
- | 2247 | if (round_glyph_positions == CAIRO_ROUND_GLYPH_POS_ON) |
|
2100 | } |
2248 | x = _cairo_fixed_from_int (_cairo_lround (glyphs[i].x)); |
2101 | 2249 | else |
|
2102 | x = _cairo_fixed_from_double (glyphs[i].x); |
2250 | x = _cairo_fixed_from_double (glyphs[i].x); |
Line -... | Line 2251... | ||
- | 2251 | x1 = x + scaled_glyph->bbox.p1.x; |
|
- | 2252 | x2 = x + scaled_glyph->bbox.p2.x; |
|
- | 2253 | ||
2103 | x1 = x + scaled_glyph->bbox.p1.x; |
2254 | if (round_glyph_positions == CAIRO_ROUND_GLYPH_POS_ON) |
2104 | x2 = x + scaled_glyph->bbox.p2.x; |
2255 | y = _cairo_fixed_from_int (_cairo_lround (glyphs[i].y)); |
2105 | 2256 | else |
|
Line 2106... | Line 2257... | ||
2106 | y = _cairo_fixed_from_double (glyphs[i].y); |
2257 | y = _cairo_fixed_from_double (glyphs[i].y); |
Line 2131... | Line 2282... | ||
2131 | *overlap_out = overlap; |
2282 | *overlap_out = overlap; |
Line 2132... | Line 2283... | ||
2132 | 2283 | ||
2133 | return CAIRO_STATUS_SUCCESS; |
2284 | return CAIRO_STATUS_SUCCESS; |
Line 2134... | Line 2285... | ||
2134 | } |
2285 | } |
2135 | 2286 | ||
2136 | void |
2287 | cairo_bool_t |
2137 | _cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t *scaled_font, |
2288 | _cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t *scaled_font, |
2138 | const cairo_glyph_t *glyphs, |
2289 | const cairo_glyph_t *glyphs, |
2139 | int num_glyphs, |
2290 | int num_glyphs, |
2140 | cairo_rectangle_int_t *extents) |
- | |
2141 | { |
2291 | cairo_rectangle_int_t *extents) |
2142 | double x0 = HUGE_VAL, x1 = -HUGE_VAL; |
2292 | { |
Line -... | Line 2293... | ||
- | 2293 | double x0, x1, y0, y1, pad; |
|
- | 2294 | int i; |
|
- | 2295 | ||
- | 2296 | /* If any of the factors are suspect (i.e. the font is broken), bail */ |
|
- | 2297 | if (scaled_font->fs_extents.max_x_advance == 0 || |
|
- | 2298 | scaled_font->fs_extents.height == 0 || |
|
- | 2299 | scaled_font->max_scale == 0) |
|
- | 2300 | { |
|
- | 2301 | return FALSE; |
|
- | 2302 | } |
|
- | 2303 | ||
- | 2304 | assert (num_glyphs); |
|
2143 | double y0 = HUGE_VAL, y1 = -HUGE_VAL; |
2305 | |
2144 | int i; |
2306 | x0 = x1 = glyphs[0].x; |
Line 2145... | Line 2307... | ||
2145 | 2307 | y0 = y1 = glyphs[0].y; |
|
2146 | for (i = 0; i < num_glyphs; i++) { |
2308 | for (i = 1; i < num_glyphs; i++) { |
2147 | double g; |
2309 | double g; |
Line 2153... | Line 2315... | ||
2153 | g = glyphs[i].y; |
2315 | g = glyphs[i].y; |
2154 | if (g < y0) y0 = g; |
2316 | if (g < y0) y0 = g; |
2155 | if (g > y1) y1 = g; |
2317 | if (g > y1) y1 = g; |
2156 | } |
2318 | } |
Line 2157... | Line -... | ||
2157 | - | ||
2158 | if (x0 <= x1 && y0 <= y1) { |
2319 | |
2159 | extents->x = floor (x0 - scaled_font->extents.max_x_advance); |
2320 | pad = MAX(scaled_font->fs_extents.max_x_advance, |
2160 | extents->width = ceil (x1 + scaled_font->extents.max_x_advance); |
2321 | scaled_font->fs_extents.height); |
2161 | extents->width -= extents->x; |
2322 | pad *= scaled_font->max_scale; |
2162 | 2323 | ||
2163 | extents->y = floor (y0 - scaled_font->extents.ascent); |
2324 | extents->x = floor (x0 - pad); |
2164 | extents->height = ceil (y1 + scaled_font->extents.descent); |
- | |
2165 | extents->height -= extents->y; |
- | |
2166 | } else { |
2325 | extents->width = ceil (x1 + pad) - extents->x; |
2167 | extents->x = extents->y = 0; |
2326 | extents->y = floor (y0 - pad); |
2168 | extents->width = extents->height = 0; |
2327 | extents->height = ceil (y1 + pad) - extents->y; |
2169 | } |
2328 | return TRUE; |
Line -... | Line 2329... | ||
- | 2329 | } |
|
- | 2330 | ||
2170 | } |
2331 | #if 0 |
2171 | 2332 | /* XXX win32 */ |
|
2172 | cairo_status_t |
2333 | cairo_status_t |
2173 | _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, |
2334 | _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, |
2174 | cairo_operator_t op, |
2335 | cairo_operator_t op, |
Line 2182... | Line 2343... | ||
2182 | unsigned int height, |
2343 | unsigned int height, |
2183 | cairo_glyph_t *glyphs, |
2344 | cairo_glyph_t *glyphs, |
2184 | int num_glyphs, |
2345 | int num_glyphs, |
2185 | cairo_region_t *clip_region) |
2346 | cairo_region_t *clip_region) |
2186 | { |
2347 | { |
2187 | cairo_status_t status; |
2348 | cairo_int_status_t status; |
2188 | cairo_surface_t *mask = NULL; |
2349 | cairo_surface_t *mask = NULL; |
2189 | cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */ |
2350 | cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */ |
2190 | cairo_surface_pattern_t mask_pattern; |
2351 | cairo_surface_pattern_t mask_pattern; |
2191 | int i; |
2352 | int i; |
Line 2213... | Line 2374... | ||
2213 | clip_region, |
2374 | clip_region, |
2214 | &remaining_glyphs); |
2375 | &remaining_glyphs); |
2215 | glyphs += num_glyphs - remaining_glyphs; |
2376 | glyphs += num_glyphs - remaining_glyphs; |
2216 | num_glyphs = remaining_glyphs; |
2377 | num_glyphs = remaining_glyphs; |
2217 | if (remaining_glyphs == 0) |
2378 | if (remaining_glyphs == 0) |
2218 | status = CAIRO_STATUS_SUCCESS; |
2379 | status = CAIRO_INT_STATUS_SUCCESS; |
2219 | if (status != CAIRO_INT_STATUS_UNSUPPORTED) |
2380 | if (status != CAIRO_INT_STATUS_UNSUPPORTED) |
2220 | return _cairo_scaled_font_set_error (scaled_font, status); |
2381 | return _cairo_scaled_font_set_error (scaled_font, status); |
2221 | } |
2382 | } |
Line 2222... | Line 2383... | ||
2222 | 2383 | ||
Line 2263... | Line 2424... | ||
2263 | case CAIRO_FORMAT_A1: |
2424 | case CAIRO_FORMAT_A1: |
2264 | mask_format = glyph_surface->format; |
2425 | mask_format = glyph_surface->format; |
2265 | break; |
2426 | break; |
2266 | case CAIRO_FORMAT_RGB16_565: |
2427 | case CAIRO_FORMAT_RGB16_565: |
2267 | case CAIRO_FORMAT_RGB24: |
2428 | case CAIRO_FORMAT_RGB24: |
- | 2429 | case CAIRO_FORMAT_RGB30: |
|
2268 | case CAIRO_FORMAT_INVALID: |
2430 | case CAIRO_FORMAT_INVALID: |
2269 | default: |
2431 | default: |
2270 | ASSERT_NOT_REACHED; |
2432 | ASSERT_NOT_REACHED; |
2271 | mask_format = CAIRO_FORMAT_ARGB32; |
2433 | mask_format = CAIRO_FORMAT_ARGB32; |
2272 | break; |
2434 | break; |
Line 2356... | Line 2518... | ||
2356 | 2518 | ||
2357 | if (mask != NULL) |
2519 | if (mask != NULL) |
2358 | cairo_surface_destroy (mask); |
2520 | cairo_surface_destroy (mask); |
2359 | return _cairo_scaled_font_set_error (scaled_font, status); |
2521 | return _cairo_scaled_font_set_error (scaled_font, status); |
- | 2522 | } |
|
Line 2360... | Line 2523... | ||
2360 | } |
2523 | #endif |
2361 | 2524 | ||
2362 | /* Add a single-device-unit rectangle to a path. */ |
2525 | /* Add a single-device-unit rectangle to a path. */ |
2363 | static cairo_status_t |
2526 | static cairo_status_t |
Line 2468... | Line 2631... | ||
2468 | _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, |
2631 | _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, |
2469 | const cairo_glyph_t *glyphs, |
2632 | const cairo_glyph_t *glyphs, |
2470 | int num_glyphs, |
2633 | int num_glyphs, |
2471 | cairo_path_fixed_t *path) |
2634 | cairo_path_fixed_t *path) |
2472 | { |
2635 | { |
2473 | cairo_status_t status; |
2636 | cairo_int_status_t status; |
2474 | int i; |
2637 | int i; |
Line 2475... | Line 2638... | ||
2475 | 2638 | ||
2476 | status = scaled_font->status; |
2639 | status = scaled_font->status; |
2477 | if (unlikely (status)) |
2640 | if (unlikely (status)) |
Line 2483... | Line 2646... | ||
2483 | 2646 | ||
2484 | status = _cairo_scaled_glyph_lookup (scaled_font, |
2647 | status = _cairo_scaled_glyph_lookup (scaled_font, |
2485 | glyphs[i].index, |
2648 | glyphs[i].index, |
2486 | CAIRO_SCALED_GLYPH_INFO_PATH, |
2649 | CAIRO_SCALED_GLYPH_INFO_PATH, |
2487 | &scaled_glyph); |
2650 | &scaled_glyph); |
2488 | if (status == CAIRO_STATUS_SUCCESS) { |
2651 | if (status == CAIRO_INT_STATUS_SUCCESS) { |
2489 | status = _cairo_path_fixed_append (path, |
2652 | status = _cairo_path_fixed_append (path, |
2490 | scaled_glyph->path, CAIRO_DIRECTION_FORWARD, |
2653 | scaled_glyph->path, |
2491 | _cairo_fixed_from_double (glyphs[i].x), |
2654 | _cairo_fixed_from_double (glyphs[i].x), |
Line 2492... | Line 2655... | ||
2492 | _cairo_fixed_from_double (glyphs[i].y)); |
2655 | _cairo_fixed_from_double (glyphs[i].y)); |
2493 | 2656 | ||
Line 2670... | Line 2833... | ||
2670 | cairo_scaled_glyph_t **scaled_glyph) |
2833 | cairo_scaled_glyph_t **scaled_glyph) |
2671 | { |
2834 | { |
2672 | cairo_scaled_glyph_page_t *page; |
2835 | cairo_scaled_glyph_page_t *page; |
2673 | cairo_status_t status; |
2836 | cairo_status_t status; |
Line -... | Line 2837... | ||
- | 2837 | ||
- | 2838 | assert (scaled_font->cache_frozen); |
|
2674 | 2839 | ||
2675 | /* only the first page in the list may contain available slots */ |
2840 | /* only the first page in the list may contain available slots */ |
2676 | if (! cairo_list_is_empty (&scaled_font->glyph_pages)) { |
2841 | if (! cairo_list_is_empty (&scaled_font->glyph_pages)) { |
2677 | page = cairo_list_last_entry (&scaled_font->glyph_pages, |
2842 | page = cairo_list_last_entry (&scaled_font->glyph_pages, |
2678 | cairo_scaled_glyph_page_t, |
2843 | cairo_scaled_glyph_page_t, |
Line 2695... | Line 2860... | ||
2695 | if (scaled_font->global_cache_frozen == FALSE) { |
2860 | if (scaled_font->global_cache_frozen == FALSE) { |
2696 | if (unlikely (cairo_scaled_glyph_page_cache.hash_table == NULL)) { |
2861 | if (unlikely (cairo_scaled_glyph_page_cache.hash_table == NULL)) { |
2697 | status = _cairo_cache_init (&cairo_scaled_glyph_page_cache, |
2862 | status = _cairo_cache_init (&cairo_scaled_glyph_page_cache, |
2698 | NULL, |
2863 | NULL, |
2699 | _cairo_scaled_glyph_page_can_remove, |
2864 | _cairo_scaled_glyph_page_can_remove, |
2700 | _cairo_scaled_glyph_page_destroy, |
2865 | _cairo_scaled_glyph_page_pluck, |
2701 | MAX_GLYPH_PAGES_CACHED); |
2866 | MAX_GLYPH_PAGES_CACHED); |
2702 | if (unlikely (status)) { |
2867 | if (unlikely (status)) { |
2703 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex); |
2868 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex); |
2704 | free (page); |
2869 | free (page); |
2705 | return status; |
2870 | return status; |
Line 2737... | Line 2902... | ||
2737 | assert (scaled_glyph == &page->glyphs[page->num_glyphs-1]); |
2902 | assert (scaled_glyph == &page->glyphs[page->num_glyphs-1]); |
Line 2738... | Line 2903... | ||
2738 | 2903 | ||
Line 2739... | Line 2904... | ||
2739 | _cairo_scaled_glyph_fini (scaled_font, scaled_glyph); |
2904 | _cairo_scaled_glyph_fini (scaled_font, scaled_glyph); |
- | 2905 | ||
- | 2906 | if (--page->num_glyphs == 0) { |
|
- | 2907 | CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex); |
|
2740 | 2908 | /* Temporarily disconnect callback to avoid recursive locking */ |
|
2741 | if (--page->num_glyphs == 0) { |
2909 | cairo_scaled_glyph_page_cache.entry_destroy = NULL; |
- | 2910 | _cairo_cache_remove (&cairo_scaled_glyph_page_cache, |
|
- | 2911 | &page->cache_entry); |
|
- | 2912 | _cairo_scaled_glyph_page_destroy (scaled_font, page); |
|
2742 | _cairo_cache_remove (&cairo_scaled_glyph_page_cache, |
2913 | cairo_scaled_glyph_page_cache.entry_destroy = _cairo_scaled_glyph_page_pluck; |
2743 | &page->cache_entry); |
2914 | CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex); |
Line 2744... | Line 2915... | ||
2744 | } |
2915 | } |
2745 | } |
2916 | } |
Line 2775... | Line 2946... | ||
2775 | _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, |
2946 | _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, |
2776 | unsigned long index, |
2947 | unsigned long index, |
2777 | cairo_scaled_glyph_info_t info, |
2948 | cairo_scaled_glyph_info_t info, |
2778 | cairo_scaled_glyph_t **scaled_glyph_ret) |
2949 | cairo_scaled_glyph_t **scaled_glyph_ret) |
2779 | { |
2950 | { |
2780 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
2951 | cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; |
2781 | cairo_scaled_glyph_t *scaled_glyph; |
2952 | cairo_scaled_glyph_t *scaled_glyph; |
2782 | cairo_scaled_glyph_info_t need_info; |
2953 | cairo_scaled_glyph_info_t need_info; |
Line 2783... | Line 2954... | ||
2783 | 2954 | ||
Line 2784... | Line 2955... | ||
2784 | *scaled_glyph_ret = NULL; |
2955 | *scaled_glyph_ret = NULL; |
2785 | 2956 | ||
Line -... | Line 2957... | ||
- | 2957 | if (unlikely (scaled_font->status)) |
|
- | 2958 | return scaled_font->status; |
|
- | 2959 | ||
2786 | if (unlikely (scaled_font->status)) |
2960 | assert (CAIRO_MUTEX_IS_LOCKED(scaled_font->mutex)); |
2787 | return scaled_font->status; |
2961 | assert (scaled_font->cache_frozen); |
Line 2788... | Line 2962... | ||
2788 | 2962 | ||
2789 | if (CAIRO_INJECT_FAULT ()) |
2963 | if (CAIRO_INJECT_FAULT ()) |
Line 2799... | Line 2973... | ||
2799 | if (unlikely (status)) |
2973 | if (unlikely (status)) |
2800 | goto err; |
2974 | goto err; |
Line 2801... | Line 2975... | ||
2801 | 2975 | ||
2802 | memset (scaled_glyph, 0, sizeof (cairo_scaled_glyph_t)); |
2976 | memset (scaled_glyph, 0, sizeof (cairo_scaled_glyph_t)); |
- | 2977 | _cairo_scaled_glyph_set_index (scaled_glyph, index); |
|
Line 2803... | Line 2978... | ||
2803 | _cairo_scaled_glyph_set_index (scaled_glyph, index); |
2978 | cairo_list_init (&scaled_glyph->dev_privates); |
2804 | 2979 | ||
2805 | /* ask backend to initialize metrics and shape fields */ |
2980 | /* ask backend to initialize metrics and shape fields */ |
2806 | status = |
2981 | status = |
Line 2859... | Line 3034... | ||
2859 | 3034 | ||
2860 | /** |
3035 | /** |
2861 | * cairo_scaled_font_get_font_face: |
3036 | * cairo_scaled_font_get_font_face: |
2862 | * @scaled_font: a #cairo_scaled_font_t |
3037 | * @scaled_font: a #cairo_scaled_font_t |
2863 | * |
3038 | * |
2864 | * Gets the font face that this scaled font uses. This is the |
3039 | * Gets the font face that this scaled font uses. This might be the |
- | 3040 | * font face passed to cairo_scaled_font_create(), but this does not |
|
2865 | * font face passed to cairo_scaled_font_create(). |
3041 | * hold true for all possible cases. |
2866 | * |
3042 | * |
- | 3043 | * Return value: The #cairo_font_face_t with which @scaled_font was |
|
2867 | * Return value: The #cairo_font_face_t with which @scaled_font was |
3044 | * created. This object is owned by cairo. To keep a reference to it, |
2868 | * created. |
3045 | * you must call cairo_scaled_font_reference(). |
2869 | * |
3046 | * |
2870 | * Since: 1.2 |
3047 | * Since: 1.2 |
2871 | **/ |
3048 | **/ |
2872 | cairo_font_face_t * |
3049 | cairo_font_face_t * |