Subversion Repositories Kolibri OS

Rev

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 *