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 35... Line 35...
35
 *	Carl D. Worth 
35
 *	Carl D. Worth 
36
 */
36
 */
Line 37... Line 37...
37
 
37
 
Line -... Line 38...
-
 
38
#include "cairoint.h"
38
#include "cairoint.h"
39
 
39
 
40
#include "cairo-clip-inline.h"
-
 
41
#include "cairo-clip-private.h"
40
#include "cairo-clip-private.h"
42
#include "cairo-error-private.h"
-
 
43
#include "cairo-list-inline.h"
-
 
44
#include "cairo-gstate-private.h"
Line 41... Line 45...
41
#include "cairo-error-private.h"
45
#include "cairo-pattern-private.h"
42
#include "cairo-gstate-private.h"
46
#include "cairo-traps-private.h"
43
 
47
 
44
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
48
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
Line 57... Line 61...
57
_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
61
_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
Line 58... Line 62...
58
 
62
 
59
static void
63
static void
Line 60... Line 64...
60
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
64
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
61
 
65
 
62
static cairo_status_t
66
static void
63
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
67
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
64
                                           const cairo_glyph_t *glyphs,
68
                                           const cairo_glyph_t *glyphs,
65
                                           int                  num_glyphs,
69
                                           int                  num_glyphs,
Line 84... Line 88...
84
 
88
 
85
cairo_status_t
89
cairo_status_t
86
_cairo_gstate_init (cairo_gstate_t  *gstate,
90
_cairo_gstate_init (cairo_gstate_t  *gstate,
87
		    cairo_surface_t *target)
91
		    cairo_surface_t *target)
88
{
-
 
89
    cairo_status_t status;
-
 
90
 
92
{
Line 91... Line 93...
91
    VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
93
    VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
Line 92... Line 94...
92
 
94
 
-
 
95
    gstate->next = NULL;
Line 93... Line 96...
93
    gstate->next = NULL;
96
 
94
 
97
    gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
Line 95... Line 98...
95
    gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
98
    gstate->opacity = 1.;
Line 109... Line 112...
109
			     CAIRO_GSTATE_DEFAULT_FONT_SIZE,
112
			     CAIRO_GSTATE_DEFAULT_FONT_SIZE,
110
			     CAIRO_GSTATE_DEFAULT_FONT_SIZE);
113
			     CAIRO_GSTATE_DEFAULT_FONT_SIZE);
Line 111... Line 114...
111
 
114
 
Line 112... Line 115...
112
    _cairo_font_options_init_default (&gstate->font_options);
115
    _cairo_font_options_init_default (&gstate->font_options);
Line 113... Line 116...
113
 
116
 
114
    _cairo_clip_init (&gstate->clip);
117
    gstate->clip = NULL;
115
 
118
 
Line 129... Line 132...
129
    gstate->source = (cairo_pattern_t *) &_cairo_pattern_black.base;
132
    gstate->source = (cairo_pattern_t *) &_cairo_pattern_black.base;
Line 130... Line 133...
130
 
133
 
131
    /* Now that the gstate is fully initialized and ready for the eventual
134
    /* Now that the gstate is fully initialized and ready for the eventual
132
     * _cairo_gstate_fini(), we can check for errors (and not worry about
135
     * _cairo_gstate_fini(), we can check for errors (and not worry about
133
     * the resource deallocation). */
136
     * the resource deallocation). */
134
    status = target->status;
-
 
135
    if (unlikely (status))
-
 
136
	return status;
-
 
137
 
-
 
138
    status = gstate->source->status;
-
 
139
    if (unlikely (status))
-
 
140
	return status;
-
 
141
 
-
 
142
    return CAIRO_STATUS_SUCCESS;
137
    return target->status;
Line 143... Line 138...
143
}
138
}
144
 
139
 
145
/**
140
/**
Line 155... Line 150...
155
    cairo_status_t status;
150
    cairo_status_t status;
Line 156... Line 151...
156
 
151
 
Line 157... Line 152...
157
    VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
152
    VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
-
 
153
 
Line 158... Line 154...
158
 
154
    gstate->op = other->op;
159
    gstate->op = other->op;
155
    gstate->opacity = other->opacity;
Line 160... Line 156...
160
 
156
 
Line 174... Line 170...
174
 
170
 
Line 175... Line 171...
175
    gstate->font_matrix = other->font_matrix;
171
    gstate->font_matrix = other->font_matrix;
Line 176... Line 172...
176
 
172
 
Line 177... Line 173...
177
    _cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
173
    _cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
178
 
174
 
179
    _cairo_clip_init_copy (&gstate->clip, &other->clip);
175
    gstate->clip = _cairo_clip_copy (other->clip);
180
 
176
 
Line 211... Line 207...
211
    gstate->previous_scaled_font = NULL;
207
    gstate->previous_scaled_font = NULL;
Line 212... Line 208...
212
 
208
 
213
    cairo_scaled_font_destroy (gstate->scaled_font);
209
    cairo_scaled_font_destroy (gstate->scaled_font);
Line 214... Line 210...
214
    gstate->scaled_font = NULL;
210
    gstate->scaled_font = NULL;
Line 215... Line 211...
215
 
211
 
Line 216... Line 212...
216
    _cairo_clip_reset (&gstate->clip);
212
    _cairo_clip_destroy (gstate->clip);
217
 
213
 
Line 301... Line 297...
301
 * @child: the new child target
297
 * @child: the new child target
302
 *
298
 *
303
 * Redirect @gstate rendering to a "child" target. The original
299
 * Redirect @gstate rendering to a "child" target. The original
304
 * "parent" target with which the gstate was created will not be
300
 * "parent" target with which the gstate was created will not be
305
 * affected. See _cairo_gstate_get_target().
301
 * affected. See _cairo_gstate_get_target().
306
 *
-
 
307
 * Unless the redirected target has the same device offsets as the
-
 
308
 * original #cairo_t target, the clip will be INVALID after this call,
-
 
309
 * and the caller should either recreate or reset the clip.
-
 
310
 **/
302
 **/
311
cairo_status_t
303
cairo_status_t
312
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
304
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
313
{
305
{
314
    cairo_matrix_t matrix;
-
 
315
 
-
 
316
    /* If this gstate is already redirected, this is an error; we need a
306
    /* If this gstate is already redirected, this is an error; we need a
317
     * new gstate to be able to redirect */
307
     * new gstate to be able to redirect */
318
    assert (gstate->parent_target == NULL);
308
    assert (gstate->parent_target == NULL);
Line 319... Line 309...
319
 
309
 
320
    /* Set up our new parent_target based on our current target;
310
    /* Set up our new parent_target based on our current target;
321
     * gstate->parent_target will take the ref that is held by gstate->target
311
     * gstate->parent_target will take the ref that is held by gstate->target
322
     */
-
 
323
    cairo_surface_destroy (gstate->parent_target);
312
     */
Line 324... Line 313...
324
    gstate->parent_target = gstate->target;
313
    gstate->parent_target = gstate->target;
325
 
314
 
326
    /* Now set up our new target; we overwrite gstate->target directly,
315
    /* Now set up our new target; we overwrite gstate->target directly,
Line 330... Line 319...
330
    cairo_list_move (&gstate->device_transform_observer.link,
319
    cairo_list_move (&gstate->device_transform_observer.link,
331
		     &gstate->target->device_transform_observers);
320
		     &gstate->target->device_transform_observers);
Line 332... Line 321...
332
 
321
 
333
    /* The clip is in surface backend coordinates for the previous target;
322
    /* The clip is in surface backend coordinates for the previous target;
334
     * translate it into the child's backend coordinates. */
323
     * translate it into the child's backend coordinates. */
-
 
324
    _cairo_clip_destroy (gstate->clip);
335
    cairo_matrix_init_translate (&matrix,
325
    gstate->clip = _cairo_clip_copy_with_translation (gstate->next->clip,
336
				 child->device_transform.x0 - gstate->parent_target->device_transform.x0,
326
						      child->device_transform.x0 - gstate->parent_target->device_transform.x0,
-
 
327
						      child->device_transform.y0 - gstate->parent_target->device_transform.y0);
337
				 child->device_transform.y0 - gstate->parent_target->device_transform.y0);
328
 
338
    _cairo_clip_reset (&gstate->clip);
-
 
339
    return _cairo_clip_init_copy_transformed (&gstate->clip,
-
 
340
					      &gstate->next->clip,
-
 
341
					      &matrix);
329
    return CAIRO_STATUS_SUCCESS;
Line 342... Line 330...
342
}
330
}
343
 
331
 
344
/**
332
/**
345
 * _cairo_gstate_is_redirected
333
 * _cairo_gstate_is_group:
346
 * @gstate: a #cairo_gstate_t
334
 * @gstate: a #cairo_gstate_t
-
 
335
 *
347
 *
336
 * Check if _cairo_gstate_redirect_target has been called on the head
348
 * This space left intentionally blank.
337
 * of the stack.
349
 *
338
 *
350
 * Return value: %TRUE if the gstate is redirected to a target
339
 * Return value: %TRUE if @gstate is redirected to a target different
351
 * different than the original, %FALSE otherwise.
340
 * than the previous state in the stack, %FALSE otherwise.
352
 **/
341
 **/
353
cairo_bool_t
342
cairo_bool_t
354
_cairo_gstate_is_redirected (cairo_gstate_t *gstate)
343
_cairo_gstate_is_group (cairo_gstate_t *gstate)
355
{
344
{
Line 356... Line 345...
356
    return (gstate->target != gstate->original_target);
345
    return gstate->parent_target != NULL;
357
}
346
}
358
 
347
 
Line 370... Line 359...
370
{
359
{
371
    return gstate->target;
360
    return gstate->target;
372
}
361
}
Line 373... Line 362...
373
 
362
 
374
/**
-
 
375
 * _cairo_gstate_get_parent_target:
-
 
376
 * @gstate: a #cairo_gstate_t
-
 
377
 *
-
 
378
 * Return the parent surface of the current drawing target surface;
-
 
379
 * if this particular gstate isn't a redirect gstate, this will return %NULL.
-
 
380
 **/
-
 
381
cairo_surface_t *
-
 
382
_cairo_gstate_get_parent_target (cairo_gstate_t *gstate)
-
 
383
{
-
 
384
    return gstate->parent_target;
-
 
385
}
-
 
386
 
-
 
387
/**
363
/**
388
 * _cairo_gstate_get_original_target:
364
 * _cairo_gstate_get_original_target:
389
 * @gstate: a #cairo_gstate_t
365
 * @gstate: a #cairo_gstate_t
390
 *
366
 *
391
 * Return the original target with which @gstate was created. This
367
 * Return the original target with which @gstate was created. This
Line 406... Line 382...
406
 * @gstate: a #cairo_gstate_t
382
 * @gstate: a #cairo_gstate_t
407
 *
383
 *
408
 * This space left intentionally blank.
384
 * This space left intentionally blank.
409
 *
385
 *
410
 * Return value: a pointer to the gstate's #cairo_clip_t structure.
386
 * Return value: a pointer to the gstate's #cairo_clip_t structure.
411
 */
387
 **/
412
cairo_clip_t *
388
cairo_clip_t *
413
_cairo_gstate_get_clip (cairo_gstate_t *gstate)
389
_cairo_gstate_get_clip (cairo_gstate_t *gstate)
414
{
390
{
415
    return &gstate->clip;
391
    return gstate->clip;
416
}
392
}
Line 417... Line 393...
417
 
393
 
418
cairo_status_t
394
cairo_status_t
419
_cairo_gstate_set_source (cairo_gstate_t  *gstate,
395
_cairo_gstate_set_source (cairo_gstate_t  *gstate,
Line 454... Line 430...
454
{
430
{
455
    return gstate->op;
431
    return gstate->op;
456
}
432
}
Line 457... Line 433...
457
 
433
 
-
 
434
cairo_status_t
-
 
435
_cairo_gstate_set_opacity (cairo_gstate_t *gstate, double op)
-
 
436
{
-
 
437
    gstate->opacity = op;
-
 
438
 
-
 
439
    return CAIRO_STATUS_SUCCESS;
-
 
440
}
-
 
441
 
-
 
442
double
-
 
443
_cairo_gstate_get_opacity (cairo_gstate_t *gstate)
-
 
444
{
-
 
445
    return gstate->opacity;
-
 
446
}
-
 
447
 
458
cairo_status_t
448
cairo_status_t
459
_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance)
449
_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance)
460
{
450
{
Line 461... Line 451...
461
    gstate->tolerance = tolerance;
451
    gstate->tolerance = tolerance;
Line 526... Line 516...
526
}
516
}
Line 527... Line 517...
527
 
517
 
528
cairo_status_t
518
cairo_status_t
529
_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset)
519
_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset)
530
{
520
{
531
    unsigned int i;
521
    double dash_total, on_total, off_total;
Line 532... Line -...
532
    double dash_total;
-
 
533
 
522
    int i, j;
Line 534... Line 523...
534
    if (gstate->stroke_style.dash)
523
 
Line 535... Line 524...
535
	free (gstate->stroke_style.dash);
524
    free (gstate->stroke_style.dash);
Line 546... Line 535...
546
    if (unlikely (gstate->stroke_style.dash == NULL)) {
535
    if (unlikely (gstate->stroke_style.dash == NULL)) {
547
	gstate->stroke_style.num_dashes = 0;
536
	gstate->stroke_style.num_dashes = 0;
548
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
537
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
549
    }
538
    }
Line 550... Line 539...
550
 
539
 
-
 
540
    on_total = off_total = dash_total = 0.0;
-
 
541
    for (i = j = 0; i < num_dashes; i++) {
-
 
542
	if (dash[i] < 0)
Line 551... Line -...
551
    memcpy (gstate->stroke_style.dash, dash, gstate->stroke_style.num_dashes * sizeof (double));
-
 
552
 
543
	    return _cairo_error (CAIRO_STATUS_INVALID_DASH);
553
    dash_total = 0.0;
544
 
554
    for (i = 0; i < gstate->stroke_style.num_dashes; i++) {
545
	if (dash[i] == 0 && i > 0 && i < num_dashes - 1) {
Line -... Line 546...
-
 
546
	    if (dash[++i] < 0)
-
 
547
		return _cairo_error (CAIRO_STATUS_INVALID_DASH);
-
 
548
 
555
	if (gstate->stroke_style.dash[i] < 0)
549
	    gstate->stroke_style.dash[j-1] += dash[i];
-
 
550
	    gstate->stroke_style.num_dashes -= 2;
-
 
551
	} else
-
 
552
	    gstate->stroke_style.dash[j++] = dash[i];
-
 
553
 
-
 
554
	if (dash[i]) {
-
 
555
	    dash_total += dash[i];
-
 
556
	    if ((i & 1) == 0)
-
 
557
		on_total += dash[i];
556
	    return _cairo_error (CAIRO_STATUS_INVALID_DASH);
558
	    else
Line 557... Line 559...
557
 
559
		off_total += dash[i];
558
	dash_total += gstate->stroke_style.dash[i];
560
	}
Line 559... Line 561...
559
    }
561
    }
560
 
562
 
561
    if (dash_total == 0.0)
563
    if (dash_total == 0.0)
562
	return _cairo_error (CAIRO_STATUS_INVALID_DASH);
564
	return _cairo_error (CAIRO_STATUS_INVALID_DASH);
-
 
565
 
-
 
566
    /* An odd dash value indicate symmetric repeating, so the total
-
 
567
     * is twice as long. */
-
 
568
    if (gstate->stroke_style.num_dashes & 1) {
-
 
569
	dash_total *= 2;
-
 
570
	on_total += off_total;
-
 
571
    }
-
 
572
 
-
 
573
    if (dash_total - on_total < CAIRO_FIXED_ERROR_DOUBLE) {
-
 
574
	/* Degenerate dash -> solid line */
-
 
575
	free (gstate->stroke_style.dash);
Line 563... Line 576...
563
 
576
	gstate->stroke_style.dash = NULL;
564
    /* An odd dash value indicate symmetric repeating, so the total
577
	gstate->stroke_style.num_dashes = 0;
565
     * is twice as long. */
578
	gstate->stroke_style.dash_offset = 0.0;
566
    if (gstate->stroke_style.num_dashes & 1)
579
	return CAIRO_STATUS_SUCCESS;
Line 799... Line 812...
799
    cairo_matrix_transform_point (&gstate->ctm, x, y);
812
    cairo_matrix_transform_point (&gstate->ctm, x, y);
800
    cairo_matrix_transform_point (&gstate->target->device_transform, x, y);
813
    cairo_matrix_transform_point (&gstate->target->device_transform, x, y);
801
}
814
}
Line 802... Line 815...
802
 
815
 
-
 
816
void
-
 
817
_do_cairo_gstate_user_to_backend_distance (cairo_gstate_t *gstate, double *x, double *y)
-
 
818
{
-
 
819
    cairo_matrix_transform_distance (&gstate->ctm, x, y);
-
 
820
    cairo_matrix_transform_distance (&gstate->target->device_transform, x, y);
-
 
821
}
-
 
822
 
803
void
823
void
804
_do_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
824
_do_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
805
{
825
{
806
    cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y);
826
    cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y);
807
    cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
827
    cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
Line 808... Line 828...
808
}
828
}
-
 
829
 
-
 
830
void
-
 
831
_do_cairo_gstate_backend_to_user_distance (cairo_gstate_t *gstate, double *x, double *y)
-
 
832
{
-
 
833
    cairo_matrix_transform_distance (&gstate->target->device_transform_inverse, x, y);
-
 
834
    cairo_matrix_transform_distance (&gstate->ctm_inverse, x, y);
-
 
835
}
809
 
836
 
810
void
837
void
811
_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
838
_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
812
                                         double *x1, double *y1,
839
                                         double *x1, double *y1,
813
                                         double *x2, double *y2,
840
                                         double *x2, double *y2,
814
                                         cairo_bool_t *is_tight)
841
                                         cairo_bool_t *is_tight)
Line -... Line 842...
-
 
842
{
-
 
843
    cairo_matrix_t matrix_inverse;
-
 
844
 
815
{
845
    if (! _cairo_matrix_is_identity (&gstate->target->device_transform_inverse) ||
816
    cairo_matrix_t matrix_inverse;
846
    ! _cairo_matrix_is_identity (&gstate->ctm_inverse))
817
 
847
    {
818
    cairo_matrix_multiply (&matrix_inverse,
848
	cairo_matrix_multiply (&matrix_inverse,
819
                           &gstate->target->device_transform_inverse,
849
			       &gstate->target->device_transform_inverse,
820
			   &gstate->ctm_inverse);
850
			       &gstate->ctm_inverse);
Line -... Line 851...
-
 
851
	_cairo_matrix_transform_bounding_box (&matrix_inverse,
-
 
852
					      x1, y1, x2, y2, is_tight);
-
 
853
    }
-
 
854
 
-
 
855
    else
-
 
856
    {
-
 
857
	if (is_tight)
821
    _cairo_matrix_transform_bounding_box (&matrix_inverse,
858
	    *is_tight = TRUE;
822
					  x1, y1, x2, y2, is_tight);
859
    }
823
}
860
}
824
 
861
 
825
/* XXX: NYI
862
/* XXX: NYI
Line 946... Line 983...
946
    _cairo_gstate_copy_transformed_pattern (gstate, pattern,
983
    _cairo_gstate_copy_transformed_pattern (gstate, pattern,
947
					    mask,
984
					    mask,
948
					    &gstate->ctm_inverse);
985
					    &gstate->ctm_inverse);
949
}
986
}
Line 950... Line -...
950
 
-
 
951
/* We need to take a copy of the clip so that the lower layers may modify it
-
 
952
 * by, perhaps, intersecting it with the operation extents and other paths.
-
 
953
 */
-
 
954
#define _gstate_get_clip(G, C) _cairo_clip_init_copy ((C), &(G)->clip)
-
 
955
 
-
 
956
static cairo_bool_t
-
 
957
_clipped (cairo_gstate_t *gstate)
-
 
958
{
-
 
959
    cairo_rectangle_int_t extents;
-
 
960
 
-
 
961
    if (gstate->clip.all_clipped)
-
 
962
	return TRUE;
-
 
963
 
-
 
964
    /* XXX consider applying a surface clip? */
-
 
965
 
-
 
966
    if (gstate->clip.path == NULL)
-
 
967
	return FALSE;
-
 
968
 
-
 
969
    if (_cairo_surface_get_extents (gstate->target, &extents)) {
-
 
970
	if (extents.width == 0 || extents.height == 0)
-
 
971
	    return TRUE;
-
 
972
 
-
 
973
	if (! _cairo_rectangle_intersect (&extents,
-
 
974
					  &gstate->clip.path->extents))
-
 
975
	{
-
 
976
	    return TRUE;
-
 
977
	}
-
 
978
    }
-
 
979
 
-
 
980
    /* perform a simple query to exclude trivial all-clipped cases */
-
 
981
    return _cairo_clip_get_region (&gstate->clip, NULL) == CAIRO_INT_STATUS_NOTHING_TO_DO;
-
 
982
}
-
 
983
 
987
 
984
static cairo_operator_t
988
static cairo_operator_t
985
_reduce_op (cairo_gstate_t *gstate)
989
_reduce_op (cairo_gstate_t *gstate)
986
{
990
{
987
    cairo_operator_t op;
991
    cairo_operator_t op;
Line 1018... Line 1022...
1018
    }
1022
    }
Line 1019... Line 1023...
1019
 
1023
 
1020
    return op;
1024
    return op;
Line -... Line 1025...
-
 
1025
}
-
 
1026
 
-
 
1027
static cairo_status_t
-
 
1028
_cairo_gstate_get_pattern_status (const cairo_pattern_t *pattern)
-
 
1029
{
-
 
1030
    if (unlikely (pattern->type == CAIRO_PATTERN_TYPE_MESH &&
-
 
1031
		  ((const cairo_mesh_pattern_t *) pattern)->current_patch))
-
 
1032
    {
-
 
1033
	/* If current patch != NULL, the pattern is under construction
-
 
1034
	 * and cannot be used as a source */
-
 
1035
	return CAIRO_STATUS_INVALID_MESH_CONSTRUCTION;
-
 
1036
    }
-
 
1037
 
-
 
1038
    return pattern->status;
1021
}
1039
}
1022
 
1040
 
1023
cairo_status_t
1041
cairo_status_t
1024
_cairo_gstate_paint (cairo_gstate_t *gstate)
1042
_cairo_gstate_paint (cairo_gstate_t *gstate)
1025
{
1043
{
1026
    cairo_pattern_union_t source_pattern;
-
 
1027
    const cairo_pattern_t *pattern;
1044
    cairo_pattern_union_t source_pattern;
1028
    cairo_clip_t clip;
1045
    const cairo_pattern_t *pattern;
Line -... Line 1046...
-
 
1046
    cairo_status_t status;
1029
    cairo_status_t status;
1047
    cairo_operator_t op;
1030
    cairo_operator_t op;
1048
 
Line 1031... Line 1049...
1031
 
1049
    status = _cairo_gstate_get_pattern_status (gstate->source);
1032
    if (unlikely (gstate->source->status))
1050
    if (unlikely (status))
Line 1033... Line 1051...
1033
	return gstate->source->status;
1051
	return status;
1034
 
1052
 
Line 1035... Line 1053...
1035
    if (gstate->op == CAIRO_OPERATOR_DEST)
1053
    if (gstate->op == CAIRO_OPERATOR_DEST)
1036
	return CAIRO_STATUS_SUCCESS;
1054
	return CAIRO_STATUS_SUCCESS;
1037
 
1055
 
1038
    if (_clipped (gstate))
1056
    if (_cairo_clip_is_all_clipped (gstate->clip))
1039
	return CAIRO_STATUS_SUCCESS;
1057
	return CAIRO_STATUS_SUCCESS;
1040
 
1058
 
1041
    op = _reduce_op (gstate);
1059
    op = _reduce_op (gstate);
Line 1042... Line 1060...
1042
    if (op == CAIRO_OPERATOR_CLEAR) {
1060
    if (op == CAIRO_OPERATOR_CLEAR) {
1043
	pattern = &_cairo_pattern_clear.base;
1061
	pattern = &_cairo_pattern_clear.base;
1044
    } else {
1062
    } else {
1045
	_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
-
 
1046
	pattern = &source_pattern.base;
-
 
1047
    }
-
 
1048
 
1063
	_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
Line 1049... Line 1064...
1049
    status = _cairo_surface_paint (gstate->target,
1064
	pattern = &source_pattern.base;
1050
				   op, pattern,
1065
    }
1051
				   _gstate_get_clip (gstate, &clip));
1066
 
1052
    _cairo_clip_fini (&clip);
1067
    return _cairo_surface_paint (gstate->target,
1053
 
1068
				 op, pattern,
1054
    return status;
1069
				 gstate->clip);
1055
}
1070
}
1056
 
-
 
1057
cairo_status_t
1071
 
Line -... Line 1072...
-
 
1072
cairo_status_t
1058
_cairo_gstate_mask (cairo_gstate_t  *gstate,
1073
_cairo_gstate_mask (cairo_gstate_t  *gstate,
1059
		    cairo_pattern_t *mask)
1074
		    cairo_pattern_t *mask)
Line -... Line 1075...
-
 
1075
{
1060
{
1076
    cairo_pattern_union_t source_pattern, mask_pattern;
1061
    cairo_pattern_union_t source_pattern, mask_pattern;
1077
    const cairo_pattern_t *source;
Line 1062... Line 1078...
1062
    const cairo_pattern_t *source;
1078
    cairo_operator_t op;
1063
    cairo_operator_t op;
1079
    cairo_status_t status;
Line 1064... Line 1080...
1064
    cairo_clip_t clip;
1080
 
1065
    cairo_status_t status;
1081
    status = _cairo_gstate_get_pattern_status (mask);
Line -... Line 1082...
-
 
1082
    if (unlikely (status))
-
 
1083
	return status;
1066
 
1084
 
1067
    if (unlikely (mask->status))
1085
    status = _cairo_gstate_get_pattern_status (gstate->source);
Line 1068... Line 1086...
1068
	return mask->status;
1086
    if (unlikely (status))
1069
 
1087
	return status;
Line 1093... Line 1111...
1093
	source = &source_pattern.base;
1111
	source = &source_pattern.base;
1094
    }
1112
    }
1095
    _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
1113
    _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
Line 1096... Line 1114...
1096
 
1114
 
1097
    if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
1115
    if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
1098
	mask_pattern.type == CAIRO_PATTERN_TYPE_SOLID &&
1116
	mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
1099
	_cairo_operator_bounded_by_source (op))
1117
	_cairo_operator_bounded_by_source (op))
1100
    {
1118
    {
1101
	const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
1119
	const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
Line 1115... Line 1133...
1115
 
1133
 
Line 1116... Line 1134...
1116
	_cairo_pattern_init_solid (&source_pattern.solid, &combined);
1134
	_cairo_pattern_init_solid (&source_pattern.solid, &combined);
1117
 
1135
 
1118
	status = _cairo_surface_paint (gstate->target, op,
1136
	status = _cairo_surface_paint (gstate->target, op,
1119
				       &source_pattern.base,
1137
				       &source_pattern.base,
1120
				       _gstate_get_clip (gstate, &clip));
1138
				       gstate->clip);
1121
    }
1139
    }
1122
    else
1140
    else
1123
    {
1141
    {
1124
	status = _cairo_surface_mask (gstate->target, op,
1142
	status = _cairo_surface_mask (gstate->target, op,
1125
				      source,
1143
				      source,
1126
				      &mask_pattern.base,
1144
				      &mask_pattern.base,
1127
				      _gstate_get_clip (gstate, &clip));
-
 
Line 1128... Line 1145...
1128
    }
1145
				      gstate->clip);
1129
    _cairo_clip_fini (&clip);
1146
    }
Line 1130... Line 1147...
1130
 
1147
 
1131
    return status;
1148
    return status;
1132
}
1149
}
1133
 
1150
 
1134
cairo_status_t
1151
cairo_status_t
1135
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1152
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1136
{
-
 
1137
    cairo_pattern_union_t source_pattern;
1153
{
Line -... Line 1154...
-
 
1154
    cairo_pattern_union_t source_pattern;
1138
    cairo_stroke_style_t style;
1155
    cairo_stroke_style_t style;
1139
    double dash[2];
1156
    double dash[2];
Line 1140... Line 1157...
1140
    cairo_clip_t clip;
1157
    cairo_status_t status;
1141
    cairo_status_t status;
1158
 
Line 1142... Line 1159...
1142
 
1159
    status = _cairo_gstate_get_pattern_status (gstate->source);
1143
    if (unlikely (gstate->source->status))
1160
    if (unlikely (status))
Line 1144... Line 1161...
1144
	return gstate->source->status;
1161
	return status;
1145
 
1162
 
Line -... Line 1163...
-
 
1163
    if (gstate->op == CAIRO_OPERATOR_DEST)
-
 
1164
	return CAIRO_STATUS_SUCCESS;
1146
    if (gstate->op == CAIRO_OPERATOR_DEST)
1165
 
1147
	return CAIRO_STATUS_SUCCESS;
1166
    if (gstate->stroke_style.line_width <= 0.0)
1148
 
1167
	return CAIRO_STATUS_SUCCESS;
1149
    if (gstate->stroke_style.line_width <= 0.0)
1168
 
1150
	return CAIRO_STATUS_SUCCESS;
1169
    if (_cairo_clip_is_all_clipped (gstate->clip))
Line 1161... Line 1180...
1161
					      &style.num_dashes);
1180
					      &style.num_dashes);
1162
    }
1181
    }
Line 1163... Line 1182...
1163
 
1182
 
Line 1164... Line 1183...
1164
    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
1183
    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
1165
 
1184
 
1166
    status = _cairo_surface_stroke (gstate->target,
1185
    return _cairo_surface_stroke (gstate->target,
1167
				    gstate->op,
1186
				  gstate->op,
1168
				    &source_pattern.base,
1187
				  &source_pattern.base,
1169
				    path,
1188
				  path,
1170
				    &style,
1189
				  &style,
1171
				    &gstate->ctm,
1190
				  &gstate->ctm,
1172
				    &gstate->ctm_inverse,
1191
				  &gstate->ctm_inverse,
1173
				    gstate->tolerance,
1192
				  gstate->tolerance,
1174
				    gstate->antialias,
-
 
1175
				    _gstate_get_clip (gstate, &clip));
-
 
1176
    _cairo_clip_fini (&clip);
-
 
1177
 
1193
				  gstate->antialias,
Line 1178... Line 1194...
1178
    return status;
1194
				  gstate->clip);
1179
}
1195
}
1180
 
1196
 
Line 1217... Line 1233...
1217
    limit.p2.y = limit.p1.y + 2;
1233
    limit.p2.y = limit.p1.y + 2;
Line 1218... Line 1234...
1218
 
1234
 
1219
    _cairo_traps_init (&traps);
1235
    _cairo_traps_init (&traps);
Line 1220... Line 1236...
1220
    _cairo_traps_limit (&traps, &limit, 1);
1236
    _cairo_traps_limit (&traps, &limit, 1);
1221
 
1237
 
1222
    status = _cairo_path_fixed_stroke_to_traps (path,
1238
    status = _cairo_path_fixed_stroke_polygon_to_traps (path,
1223
						&gstate->stroke_style,
1239
							&gstate->stroke_style,
1224
						&gstate->ctm,
1240
							&gstate->ctm,
1225
						&gstate->ctm_inverse,
1241
							&gstate->ctm_inverse,
Line 1237... Line 1253...
1237
}
1253
}
Line 1238... Line 1254...
1238
 
1254
 
1239
cairo_status_t
1255
cairo_status_t
1240
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1256
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1241
{
-
 
1242
    cairo_clip_t clip;
1257
{
Line -... Line 1258...
-
 
1258
    cairo_status_t status;
1243
    cairo_status_t status;
1259
 
1244
 
1260
    status = _cairo_gstate_get_pattern_status (gstate->source);
Line 1245... Line 1261...
1245
    if (unlikely (gstate->source->status))
1261
    if (unlikely (status))
1246
	return gstate->source->status;
1262
	return status;
Line 1247... Line 1263...
1247
 
1263
 
1248
    if (gstate->op == CAIRO_OPERATOR_DEST)
1264
    if (gstate->op == CAIRO_OPERATOR_DEST)
Line -... Line 1265...
-
 
1265
	return CAIRO_STATUS_SUCCESS;
-
 
1266
 
1249
	return CAIRO_STATUS_SUCCESS;
1267
    if (_cairo_clip_is_all_clipped (gstate->clip))
1250
 
1268
	return CAIRO_STATUS_SUCCESS;
1251
    if (_clipped (gstate))
1269
 
Line 1252... Line 1270...
1252
	return CAIRO_STATUS_SUCCESS;
1270
    assert (gstate->opacity == 1.0);
1253
 
1271
 
1254
    if (_cairo_path_fixed_fill_is_empty (path)) {
1272
    if (_cairo_path_fixed_fill_is_empty (path)) {
1255
	if (_cairo_operator_bounded_by_mask (gstate->op))
1273
	if (_cairo_operator_bounded_by_mask (gstate->op))
1256
	    return CAIRO_STATUS_SUCCESS;
1274
	    return CAIRO_STATUS_SUCCESS;
1257
 
1275
 
1258
	status = _cairo_surface_paint (gstate->target,
1276
	status = _cairo_surface_paint (gstate->target,
1259
				       CAIRO_OPERATOR_CLEAR,
1277
				       CAIRO_OPERATOR_CLEAR,
1260
				       &_cairo_pattern_clear.base,
1278
				       &_cairo_pattern_clear.base,
Line 1281... Line 1299...
1281
	    box.p1.y <= _cairo_fixed_from_int (extents.y) &&
1299
	    box.p1.y <= _cairo_fixed_from_int (extents.y) &&
1282
	    box.p2.x >= _cairo_fixed_from_int (extents.x + extents.width) &&
1300
	    box.p2.x >= _cairo_fixed_from_int (extents.x + extents.width) &&
1283
	    box.p2.y >= _cairo_fixed_from_int (extents.y + extents.height))
1301
	    box.p2.y >= _cairo_fixed_from_int (extents.y + extents.height))
1284
	{
1302
	{
1285
	    status = _cairo_surface_paint (gstate->target, op, pattern,
1303
	    status = _cairo_surface_paint (gstate->target, op, pattern,
1286
					   _gstate_get_clip (gstate, &clip));
1304
					   gstate->clip);
1287
	}
1305
	}
1288
	else
1306
	else
1289
	{
1307
	{
1290
	    status = _cairo_surface_fill (gstate->target, op, pattern,
1308
	    status = _cairo_surface_fill (gstate->target, op, pattern,
1291
					  path,
1309
					  path,
1292
					  gstate->fill_rule,
1310
					  gstate->fill_rule,
1293
					  gstate->tolerance,
1311
					  gstate->tolerance,
1294
					  gstate->antialias,
1312
					  gstate->antialias,
1295
					  _gstate_get_clip (gstate, &clip));
1313
					  gstate->clip);
1296
	}
1314
	}
1297
    }
1315
    }
Line 1298... Line -...
1298
 
-
 
1299
    _cairo_clip_fini (&clip);
-
 
1300
 
1316
 
1301
    return status;
1317
    return status;
Line 1302... Line 1318...
1302
}
1318
}
1303
 
1319
 
Line 1318... Line 1334...
1318
cairo_bool_t
1334
cairo_bool_t
1319
_cairo_gstate_in_clip (cairo_gstate_t	  *gstate,
1335
_cairo_gstate_in_clip (cairo_gstate_t	  *gstate,
1320
		       double		   x,
1336
		       double		   x,
1321
		       double		   y)
1337
		       double		   y)
1322
{
1338
{
1323
    cairo_clip_path_t *clip_path;
1339
    cairo_clip_t *clip = gstate->clip;
-
 
1340
    int i;
Line 1324... Line 1341...
1324
 
1341
 
1325
    if (gstate->clip.all_clipped)
1342
    if (_cairo_clip_is_all_clipped (clip))
Line 1326... Line -...
1326
	return FALSE;
-
 
1327
 
1343
	return FALSE;
1328
    clip_path = gstate->clip.path;
1344
 
Line 1329... Line 1345...
1329
    if (clip_path == NULL)
1345
    if (clip == NULL)
Line 1330... Line 1346...
1330
	return TRUE;
1346
	return TRUE;
1331
 
1347
 
1332
    _cairo_gstate_user_to_backend (gstate, &x, &y);
1348
    _cairo_gstate_user_to_backend (gstate, &x, &y);
1333
 
1349
 
1334
    if (x <  clip_path->extents.x ||
1350
    if (x <  clip->extents.x ||
1335
	x >= clip_path->extents.x + clip_path->extents.width ||
1351
	x >= clip->extents.x + clip->extents.width ||
1336
	y <  clip_path->extents.y ||
1352
	y <  clip->extents.y ||
Line -... Line 1353...
-
 
1353
	y >= clip->extents.y + clip->extents.height)
-
 
1354
    {
-
 
1355
	return FALSE;
-
 
1356
    }
-
 
1357
 
-
 
1358
    if (clip->num_boxes) {
-
 
1359
	int fx, fy;
-
 
1360
 
-
 
1361
	fx = _cairo_fixed_from_double (x);
-
 
1362
	fy = _cairo_fixed_from_double (y);
-
 
1363
	for (i = 0; i < clip->num_boxes; i++) {
-
 
1364
	    if (fx >= clip->boxes[i].p1.x && fx <= clip->boxes[i].p2.x &&
-
 
1365
		fy >= clip->boxes[i].p1.y && fy <= clip->boxes[i].p2.y)
-
 
1366
		break;
-
 
1367
	}
-
 
1368
	if (i == clip->num_boxes)
1337
	y >= clip_path->extents.y + clip_path->extents.height)
1369
	    return FALSE;
1338
    {
1370
    }
1339
	return FALSE;
1371
 
1340
    }
1372
    if (clip->path) {
1341
 
1373
	cairo_clip_path_t *clip_path = clip->path;
1342
    do {
1374
	do {
1343
	if (! _cairo_path_fixed_in_fill (&clip_path->path,
1375
	    if (! _cairo_path_fixed_in_fill (&clip_path->path,
-
 
1376
					     clip_path->fill_rule,
Line 1344... Line 1377...
1344
					 clip_path->fill_rule,
1377
					     clip_path->tolerance,
1345
					 clip_path->tolerance,
1378
					     x, y))
Line 1346... Line 1379...
1346
					 x, y))
1379
		return FALSE;
Line 1363... Line 1396...
1363
    cairo_surface_show_page (gstate->target);
1396
    cairo_surface_show_page (gstate->target);
1364
    return cairo_surface_status (gstate->target);
1397
    return cairo_surface_status (gstate->target);
1365
}
1398
}
Line 1366... Line 1399...
1366
 
1399
 
1367
static void
1400
static void
1368
_cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t	  *gstate,
1401
_cairo_gstate_extents_to_user_rectangle (cairo_gstate_t	  *gstate,
1369
                                               cairo_traps_t      *traps,
1402
					 const cairo_box_t *extents,
1370
                                               double *x1, double *y1,
1403
					 double *x1, double *y1,
1371
                                               double *x2, double *y2)
1404
					 double *x2, double *y2)
1372
{
-
 
1373
    cairo_box_t extents;
-
 
1374
 
-
 
1375
    if (traps->num_traps == 0) {
-
 
1376
        /* no traps, so we actually won't draw anything */
-
 
1377
	if (x1)
-
 
1378
	    *x1 = 0.0;
-
 
1379
	if (y1)
-
 
1380
	    *y1 = 0.0;
-
 
1381
	if (x2)
-
 
1382
	    *x2 = 0.0;
-
 
1383
	if (y2)
-
 
1384
	    *y2 = 0.0;
-
 
1385
    } else {
1405
{
Line 1386... Line -...
1386
	double px1, py1, px2, py2;
-
 
1387
 
-
 
1388
	_cairo_traps_extents (traps, &extents);
1406
    double px1, py1, px2, py2;
1389
 
1407
 
1390
	px1 = _cairo_fixed_to_double (extents.p1.x);
1408
    px1 = _cairo_fixed_to_double (extents->p1.x);
1391
	py1 = _cairo_fixed_to_double (extents.p1.y);
1409
    py1 = _cairo_fixed_to_double (extents->p1.y);
Line 1392... Line 1410...
1392
	px2 = _cairo_fixed_to_double (extents.p2.x);
1410
    px2 = _cairo_fixed_to_double (extents->p2.x);
1393
	py2 = _cairo_fixed_to_double (extents.p2.y);
1411
    py2 = _cairo_fixed_to_double (extents->p2.y);
1394
 
1412
 
1395
        _cairo_gstate_backend_to_user_rectangle (gstate,
1413
    _cairo_gstate_backend_to_user_rectangle (gstate,
Line 1402... Line 1420...
1402
	if (x2)
1420
    if (x2)
1403
	    *x2 = px2;
1421
	*x2 = px2;
1404
	if (y2)
1422
    if (y2)
1405
	    *y2 = py2;
1423
	*y2 = py2;
1406
    }
1424
}
1407
}
-
 
Line 1408... Line 1425...
1408
 
1425
 
1409
cairo_status_t
1426
cairo_status_t
1410
_cairo_gstate_stroke_extents (cairo_gstate_t	 *gstate,
1427
_cairo_gstate_stroke_extents (cairo_gstate_t	 *gstate,
1411
			      cairo_path_fixed_t *path,
1428
			      cairo_path_fixed_t *path,
1412
                              double *x1, double *y1,
1429
                              double *x1, double *y1,
1413
			      double *x2, double *y2)
1430
			      double *x2, double *y2)
1414
{
1431
{
1415
    cairo_status_t status;
1432
    cairo_int_status_t status;
-
 
1433
    cairo_box_t extents;
Line 1416... Line -...
1416
    cairo_traps_t traps;
-
 
1417
 
1434
    cairo_bool_t empty;
1418
    if (gstate->stroke_style.line_width <= 0.0) {
1435
 
1419
	if (x1)
1436
    if (x1)
1420
	    *x1 = 0.0;
1437
	*x1 = 0.0;
1421
	if (y1)
1438
    if (y1)
1422
	    *y1 = 0.0;
1439
	*y1 = 0.0;
1423
	if (x2)
1440
    if (x2)
1424
	    *x2 = 0.0;
1441
	*x2 = 0.0;
-
 
1442
    if (y2)
-
 
1443
	*y2 = 0.0;
1425
	if (y2)
1444
 
-
 
1445
    if (gstate->stroke_style.line_width <= 0.0)
-
 
1446
	return CAIRO_STATUS_SUCCESS;
-
 
1447
 
-
 
1448
    status = CAIRO_INT_STATUS_UNSUPPORTED;
-
 
1449
    if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
-
 
1450
	cairo_boxes_t boxes;
-
 
1451
 
-
 
1452
	_cairo_boxes_init (&boxes);
-
 
1453
	status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
-
 
1454
								&gstate->stroke_style,
-
 
1455
								&gstate->ctm,
-
 
1456
								gstate->antialias,
-
 
1457
								&boxes);
-
 
1458
	empty = boxes.num_boxes == 0;
-
 
1459
	if (! empty)
1426
	    *y2 = 0.0;
1460
	    _cairo_boxes_extents (&boxes, &extents);
Line -... Line 1461...
-
 
1461
	_cairo_boxes_fini (&boxes);
1427
	return CAIRO_STATUS_SUCCESS;
1462
    }
Line -... Line 1463...
-
 
1463
 
1428
    }
1464
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1429
 
1465
	cairo_polygon_t polygon;
1430
    _cairo_traps_init (&traps);
1466
 
1431
 
1467
	_cairo_polygon_init (&polygon, NULL, 0);
1432
    status = _cairo_path_fixed_stroke_to_traps (path,
1468
	status = _cairo_path_fixed_stroke_to_polygon (path,
1433
						&gstate->stroke_style,
1469
						      &gstate->stroke_style,
-
 
1470
						      &gstate->ctm,
-
 
1471
						      &gstate->ctm_inverse,
1434
						&gstate->ctm,
1472
						      gstate->tolerance,
-
 
1473
						      &polygon);
-
 
1474
	empty = polygon.num_edges == 0;
-
 
1475
	if (! empty)
1435
						&gstate->ctm_inverse,
1476
	    extents = polygon.extents;
1436
						gstate->tolerance,
1477
	_cairo_polygon_fini (&polygon);
1437
						&traps);
1478
    }
Line 1438... Line -...
1438
    if (likely (status == CAIRO_STATUS_SUCCESS)) {
-
 
1439
	_cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps,
-
 
1440
						       x1, y1, x2, y2);
1479
    if (! empty) {
1441
    }
1480
	_cairo_gstate_extents_to_user_rectangle (gstate, &extents,
Line 1442... Line 1481...
1442
 
1481
						 x1, y1, x2, y2);
1443
    _cairo_traps_fini (&traps);
1482
    }
1444
 
1483
 
1445
    return status;
1484
    return status;
1446
}
1485
}
1447
 
1486
 
1448
cairo_status_t
1487
cairo_status_t
1449
_cairo_gstate_fill_extents (cairo_gstate_t     *gstate,
1488
_cairo_gstate_fill_extents (cairo_gstate_t     *gstate,
-
 
1489
			    cairo_path_fixed_t *path,
Line 1450... Line -...
1450
			    cairo_path_fixed_t *path,
-
 
1451
                            double *x1, double *y1,
1490
                            double *x1, double *y1,
1452
			    double *x2, double *y2)
1491
			    double *x2, double *y2)
1453
{
1492
{
1454
    cairo_status_t status;
1493
    cairo_status_t status;
1455
    cairo_traps_t traps;
1494
    cairo_box_t extents;
1456
 
1495
    cairo_bool_t empty;
1457
    if (path->is_empty_fill) {
1496
 
1458
	if (x1)
1497
    if (x1)
-
 
1498
	*x1 = 0.0;
-
 
1499
    if (y1)
1459
	    *x1 = 0.0;
1500
	*y1 = 0.0;
-
 
1501
    if (x2)
-
 
1502
	*x2 = 0.0;
-
 
1503
    if (y2)
-
 
1504
	*y2 = 0.0;
-
 
1505
 
-
 
1506
    if (_cairo_path_fixed_fill_is_empty (path))
-
 
1507
	return CAIRO_STATUS_SUCCESS;
-
 
1508
 
-
 
1509
    if (_cairo_path_fixed_fill_is_rectilinear (path)) {
-
 
1510
	cairo_boxes_t boxes;
-
 
1511
 
-
 
1512
	_cairo_boxes_init (&boxes);
-
 
1513
	status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
-
 
1514
							      gstate->fill_rule,
1460
	if (y1)
1515
							      gstate->antialias,
-
 
1516
							      &boxes);
Line 1461... Line 1517...
1461
	    *y1 = 0.0;
1517
	empty = boxes.num_boxes == 0;
Line 1462... Line 1518...
1462
	if (x2)
1518
	if (! empty)
1463
	    *x2 = 0.0;
1519
	    _cairo_boxes_extents (&boxes, &extents);
1464
	if (y2)
1520
 
1465
	    *y2 = 0.0;
1521
	_cairo_boxes_fini (&boxes);
1466
	return CAIRO_STATUS_SUCCESS;
1522
    } else {
-
 
1523
	cairo_traps_t traps;
1467
    }
1524
 
1468
 
-
 
1469
    _cairo_traps_init (&traps);
-
 
Line 1470... Line 1525...
1470
 
1525
	_cairo_traps_init (&traps);
-
 
1526
 
-
 
1527
	status = _cairo_path_fixed_fill_to_traps (path,
-
 
1528
						  gstate->fill_rule,
-
 
1529
						  gstate->tolerance,
-
 
1530
						  &traps);
-
 
1531
	empty = traps.num_traps == 0;
Line 1471... Line 1532...
1471
    status = _cairo_path_fixed_fill_to_traps (path,
1532
	if (! empty)
1472
					      gstate->fill_rule,
1533
	    _cairo_traps_extents (&traps, &extents);
Line 1473... Line 1534...
1473
					      gstate->tolerance,
1534
 
1474
					      &traps);
1535
	_cairo_traps_fini (&traps);
1475
    if (likely (status == CAIRO_STATUS_SUCCESS)) {
1536
    }
1476
	_cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps,
1537
 
-
 
1538
    if (! empty) {
Line 1477... Line 1539...
1477
						       x1, y1, x2, y2);
1539
	_cairo_gstate_extents_to_user_rectangle (gstate, &extents,
1478
    }
1540
						 x1, y1, x2, y2);
Line 1479... Line 1541...
1479
 
1541
    }
1480
    _cairo_traps_fini (&traps);
1542
 
1481
 
1543
    return status;
-
 
1544
}
1482
    return status;
1545
 
-
 
1546
cairo_status_t
1483
}
1547
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
-
 
1548
{
1484
 
1549
    _cairo_clip_destroy (gstate->clip);
-
 
1550
    gstate->clip = NULL;
-
 
1551
 
1485
cairo_status_t
1552
    return CAIRO_STATUS_SUCCESS;
Line 1486... Line 1553...
1486
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
1553
}
1487
{
1554
 
1488
    _cairo_clip_reset (&gstate->clip);
1555
cairo_status_t
1489
 
1556
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1490
    return CAIRO_STATUS_SUCCESS;
-
 
1491
}
1557
{
Line 1492... Line 1558...
1492
 
1558
    gstate->clip =
Line 1493... Line -...
1493
cairo_status_t
-
 
1494
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1559
	_cairo_clip_intersect_path (gstate->clip,
1495
{
1560
				    path,
1496
    return _cairo_clip_clip (&gstate->clip,
-
 
1497
			     path, gstate->fill_rule,
1561
				    gstate->fill_rule,
1498
			     gstate->tolerance, gstate->antialias);
1562
				    gstate->tolerance,
1499
}
1563
				    gstate->antialias);
Line 1500... Line 1564...
1500
 
1564
    /* XXX */
1501
static cairo_bool_t
1565
    return CAIRO_STATUS_SUCCESS;
Line 1553... Line 1617...
1553
}
1617
}
Line 1554... Line 1618...
1554
 
1618
 
1555
cairo_rectangle_list_t*
1619
cairo_rectangle_list_t*
1556
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
1620
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
1557
{
-
 
1558
    cairo_clip_t clip;
1621
{
1559
    cairo_rectangle_int_t extents;
1622
    cairo_rectangle_int_t extents;
1560
    cairo_rectangle_list_t *list;
-
 
1561
 
1623
    cairo_rectangle_list_t *list;
Line 1562... Line 1624...
1562
    _cairo_clip_init_copy (&clip, &gstate->clip);
1624
    cairo_clip_t *clip;
1563
 
1625
 
-
 
1626
    if (_cairo_surface_get_extents (gstate->target, &extents))
-
 
1627
	clip = _cairo_clip_copy_intersect_rectangle (gstate->clip, &extents);
Line 1564... Line 1628...
1564
    if (_cairo_surface_get_extents (gstate->target, &extents))
1628
    else
-
 
1629
	clip = gstate->clip;
-
 
1630
 
1565
        _cairo_clip_rectangle (&clip, &extents);
1631
    list = _cairo_clip_copy_rectangle_list (clip, gstate);
Line 1566... Line 1632...
1566
 
1632
 
1567
    list = _cairo_clip_copy_rectangle_list (&clip, gstate);
1633
    if (clip != gstate->clip)
Line 1568... Line 1634...
1568
    _cairo_clip_fini (&clip);
1634
	_cairo_clip_destroy (clip);
Line 1582... Line 1648...
1582
    gstate->previous_scaled_font = gstate->scaled_font;
1648
    gstate->previous_scaled_font = gstate->scaled_font;
1583
    gstate->scaled_font = NULL;
1649
    gstate->scaled_font = NULL;
1584
}
1650
}
Line 1585... Line 1651...
1585
 
1651
 
1586
cairo_status_t
-
 
1587
_cairo_gstate_select_font_face (cairo_gstate_t       *gstate,
-
 
1588
				const char           *family,
-
 
1589
				cairo_font_slant_t    slant,
-
 
1590
				cairo_font_weight_t   weight)
-
 
1591
{
-
 
1592
    cairo_font_face_t *font_face;
-
 
1593
    cairo_status_t status;
-
 
1594
 
-
 
1595
    font_face = cairo_toy_font_face_create (family, slant, weight);
-
 
1596
    if (font_face->status)
-
 
1597
	return font_face->status;
-
 
1598
 
-
 
1599
    status = _cairo_gstate_set_font_face (gstate, font_face);
-
 
1600
    cairo_font_face_destroy (font_face);
-
 
1601
 
-
 
1602
    return status;
-
 
1603
}
-
 
1604
 
-
 
1605
cairo_status_t
1652
cairo_status_t
1606
_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
1653
_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
1607
			     double          size)
1654
			     double          size)
1608
{
1655
{
Line 1618... Line 1665...
1618
			       const cairo_matrix_t *matrix)
1665
			       const cairo_matrix_t *matrix)
1619
{
1666
{
1620
    if (memcmp (matrix, &gstate->font_matrix, sizeof (cairo_matrix_t)) == 0)
1667
    if (memcmp (matrix, &gstate->font_matrix, sizeof (cairo_matrix_t)) == 0)
1621
	return CAIRO_STATUS_SUCCESS;
1668
	return CAIRO_STATUS_SUCCESS;
Line 1622... Line -...
1622
 
-
 
1623
    if (! _cairo_matrix_is_invertible (matrix))
-
 
1624
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
-
 
1625
 
1669
 
Line 1626... Line 1670...
1626
    _cairo_gstate_unset_scaled_font (gstate);
1670
    _cairo_gstate_unset_scaled_font (gstate);
Line 1627... Line 1671...
1627
 
1671
 
Line 1826... Line 1870...
1826
 
1870
 
1827
    return cairo_scaled_font_status (gstate->scaled_font);
1871
    return cairo_scaled_font_status (gstate->scaled_font);
Line 1828... Line 1872...
1828
}
1872
}
1829
 
-
 
1830
cairo_status_t
-
 
1831
_cairo_gstate_text_to_glyphs (cairo_gstate_t	         *gstate,
-
 
1832
			      double		          x,
-
 
1833
			      double		          y,
-
 
1834
			      const char	         *utf8,
-
 
1835
			      int		          utf8_len,
-
 
1836
			      cairo_glyph_t	        **glyphs,
-
 
1837
			      int		         *num_glyphs,
-
 
1838
			      cairo_text_cluster_t      **clusters,
-
 
1839
			      int		         *num_clusters,
-
 
1840
			      cairo_text_cluster_flags_t *cluster_flags)
-
 
1841
{
-
 
1842
    cairo_status_t status;
-
 
1843
 
-
 
1844
    status = _cairo_gstate_ensure_scaled_font (gstate);
-
 
1845
    if (unlikely (status))
-
 
1846
	return status;
-
 
1847
 
-
 
1848
    return cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
-
 
1849
					     utf8, utf8_len,
-
 
1850
					     glyphs, num_glyphs,
-
 
1851
					     clusters, num_clusters,
-
 
1852
					     cluster_flags);
-
 
1853
}
-
 
1854
 
1873
 
1855
cairo_status_t
1874
cairo_status_t
1856
_cairo_gstate_set_font_face (cairo_gstate_t    *gstate,
1875
_cairo_gstate_set_font_face (cairo_gstate_t    *gstate,
1857
			     cairo_font_face_t *font_face)
1876
			     cairo_font_face_t *font_face)
1858
{
1877
{
Line 1889... Line 1908...
1889
    return cairo_scaled_font_status (gstate->scaled_font);
1908
    return cairo_scaled_font_status (gstate->scaled_font);
1890
}
1909
}
Line 1891... Line 1910...
1891
 
1910
 
1892
cairo_status_t
1911
cairo_status_t
1893
_cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
-
 
1894
				const char		   *utf8,
-
 
1895
				int			    utf8_len,
1912
_cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
1896
				const cairo_glyph_t	   *glyphs,
1913
				const cairo_glyph_t	   *glyphs,
1897
				int			    num_glyphs,
-
 
1898
				const cairo_text_cluster_t *clusters,
-
 
1899
				int			    num_clusters,
1914
				int			    num_glyphs,
1900
				cairo_text_cluster_flags_t  cluster_flags)
1915
				cairo_glyph_text_info_t    *info)
1901
{
-
 
1902
    cairo_pattern_union_t source_pattern;
-
 
1903
    const cairo_pattern_t *pattern;
1916
{
1904
    cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
-
 
1905
    cairo_glyph_t *transformed_glyphs;
1917
    cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
-
 
1918
    cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
-
 
1919
    cairo_pattern_union_t source_pattern;
-
 
1920
    cairo_glyph_t *transformed_glyphs;
1906
    cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
1921
    const cairo_pattern_t *pattern;
1907
    cairo_text_cluster_t *transformed_clusters;
1922
    cairo_text_cluster_t *transformed_clusters;
1908
    cairo_operator_t op;
1923
    cairo_operator_t op;
1909
    cairo_status_t status;
-
 
Line -... Line 1924...
-
 
1924
    cairo_status_t status;
1910
    cairo_clip_t clip;
1925
 
1911
 
1926
    status = _cairo_gstate_get_pattern_status (gstate->source);
Line 1912... Line 1927...
1912
    if (unlikely (gstate->source->status))
1927
    if (unlikely (status))
1913
	return gstate->source->status;
1928
	return status;
Line 1914... Line 1929...
1914
 
1929
 
1915
    if (gstate->op == CAIRO_OPERATOR_DEST)
1930
    if (gstate->op == CAIRO_OPERATOR_DEST)
Line 1916... Line 1931...
1916
	return CAIRO_STATUS_SUCCESS;
1931
	return CAIRO_STATUS_SUCCESS;
1917
 
1932
 
1918
    if (_clipped (gstate))
1933
    if (_cairo_clip_is_all_clipped (gstate->clip))
Line 1925... Line 1940...
1925
    transformed_glyphs = stack_transformed_glyphs;
1940
    transformed_glyphs = stack_transformed_glyphs;
1926
    transformed_clusters = stack_transformed_clusters;
1941
    transformed_clusters = stack_transformed_clusters;
Line 1927... Line 1942...
1927
 
1942
 
1928
    if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) {
1943
    if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) {
1929
	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
1944
	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
1930
	if (unlikely (transformed_glyphs == NULL)) {
1945
	if (unlikely (transformed_glyphs == NULL))
1931
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1932
	    goto CLEANUP_GLYPHS;
-
 
1933
	}
1946
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
Line 1934... Line -...
1934
    }
-
 
1935
 
1947
    }
1936
    /* Just in case */
-
 
1937
    if (!clusters)
-
 
1938
	num_clusters = 0;
1948
 
1939
 
1949
    if (info != NULL) {
1940
    if (num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) {
1950
	if (info->num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) {
1941
	transformed_clusters = cairo_text_cluster_allocate (num_clusters);
1951
	    transformed_clusters = cairo_text_cluster_allocate (info->num_clusters);
1942
	if (unlikely (transformed_clusters == NULL)) {
1952
	    if (unlikely (transformed_clusters == NULL)) {
1943
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1953
		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1944
	    goto CLEANUP_GLYPHS;
1954
		goto CLEANUP_GLYPHS;
Line 1945... Line 1955...
1945
	}
1955
	    }
1946
    }
1956
	}
1947
 
1957
 
1948
    status = _cairo_gstate_transform_glyphs_to_backend (gstate,
1958
	_cairo_gstate_transform_glyphs_to_backend (gstate,
1949
							glyphs, num_glyphs,
1959
						   glyphs, num_glyphs,
1950
							clusters,
1960
						   info->clusters,
1951
							num_clusters,
1961
						   info->num_clusters,
1952
							cluster_flags,
1962
						   info->cluster_flags,
-
 
1963
						   transformed_glyphs,
-
 
1964
						   &num_glyphs,
-
 
1965
						   transformed_clusters);
-
 
1966
    } else {
-
 
1967
	_cairo_gstate_transform_glyphs_to_backend (gstate,
-
 
1968
						   glyphs, num_glyphs,
-
 
1969
						   NULL, 0, 0,
-
 
1970
						   transformed_glyphs,
Line 1953... Line 1971...
1953
							transformed_glyphs,
1971
						   &num_glyphs,
1954
							&num_glyphs,
1972
						   NULL);
Line 1955... Line 1973...
1955
							transformed_clusters);
1973
    }
1956
 
1974
 
1957
    if (status || num_glyphs == 0)
1975
    if (num_glyphs == 0)
Line 1976... Line 1994...
1976
     *
1994
     *
1977
     * Needless to say, do this only if show_text_glyphs is not available. */
1995
     * Needless to say, do this only if show_text_glyphs is not available. */
1978
    if (cairo_surface_has_show_text_glyphs (gstate->target) ||
1996
    if (cairo_surface_has_show_text_glyphs (gstate->target) ||
1979
	_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240)
1997
	_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240)
1980
    {
1998
    {
-
 
1999
	if (info != NULL) {
1981
	status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
2000
	    status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
1982
						  utf8, utf8_len,
2001
						      info->utf8, info->utf8_len,
1983
						  transformed_glyphs, num_glyphs,
2002
						      transformed_glyphs, num_glyphs,
1984
						  transformed_clusters, num_clusters,
2003
						      transformed_clusters, info->num_clusters,
1985
						  cluster_flags,
2004
						      info->cluster_flags,
1986
						  gstate->scaled_font,
2005
						      gstate->scaled_font,
1987
						  _gstate_get_clip (gstate, &clip));
2006
						      gstate->clip);
-
 
2007
	} else {
-
 
2008
	    status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
-
 
2009
						      NULL, 0,
-
 
2010
						      transformed_glyphs, num_glyphs,
-
 
2011
						      NULL, 0, 0,
-
 
2012
						      gstate->scaled_font,
-
 
2013
						      gstate->clip);
-
 
2014
	}
1988
    }
2015
    }
1989
    else
2016
    else
1990
    {
2017
    {
1991
	cairo_path_fixed_t path;
2018
	cairo_path_fixed_t path;
Line 2000... Line 2027...
2000
	    status = _cairo_surface_fill (gstate->target, op, pattern,
2027
	    status = _cairo_surface_fill (gstate->target, op, pattern,
2001
					  &path,
2028
					  &path,
2002
					  CAIRO_FILL_RULE_WINDING,
2029
					  CAIRO_FILL_RULE_WINDING,
2003
					  gstate->tolerance,
2030
					  gstate->tolerance,
2004
					  gstate->scaled_font->options.antialias,
2031
					  gstate->scaled_font->options.antialias,
2005
					  _gstate_get_clip (gstate, &clip));
2032
					  gstate->clip);
2006
	}
2033
	}
Line 2007... Line 2034...
2007
 
2034
 
2008
	_cairo_path_fixed_fini (&path);
2035
	_cairo_path_fixed_fini (&path);
Line 2009... Line -...
2009
    }
-
 
2010
 
-
 
2011
    _cairo_clip_fini (&clip);
2036
    }
2012
 
2037
 
2013
CLEANUP_GLYPHS:
2038
CLEANUP_GLYPHS:
2014
    if (transformed_glyphs != stack_transformed_glyphs)
2039
    if (transformed_glyphs != stack_transformed_glyphs)
2015
      cairo_glyph_free (transformed_glyphs);
2040
      cairo_glyph_free (transformed_glyphs);
Line 2023... Line 2048...
2023
_cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
2048
_cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
2024
			  const cairo_glyph_t *glyphs,
2049
			  const cairo_glyph_t *glyphs,
2025
			  int		       num_glyphs,
2050
			  int		       num_glyphs,
2026
			  cairo_path_fixed_t  *path)
2051
			  cairo_path_fixed_t  *path)
2027
{
2052
{
2028
    cairo_status_t status;
-
 
2029
    cairo_glyph_t *transformed_glyphs;
-
 
2030
    cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
2053
    cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
-
 
2054
    cairo_glyph_t *transformed_glyphs;
-
 
2055
    cairo_status_t status;
Line 2031... Line 2056...
2031
 
2056
 
2032
    status = _cairo_gstate_ensure_scaled_font (gstate);
2057
    status = _cairo_gstate_ensure_scaled_font (gstate);
2033
    if (unlikely (status))
2058
    if (unlikely (status))
Line 2039... Line 2064...
2039
	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
2064
	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
2040
	if (unlikely (transformed_glyphs == NULL))
2065
	if (unlikely (transformed_glyphs == NULL))
2041
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2066
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2042
    }
2067
    }
Line 2043... Line 2068...
2043
 
2068
 
2044
    status = _cairo_gstate_transform_glyphs_to_backend (gstate,
2069
    _cairo_gstate_transform_glyphs_to_backend (gstate,
2045
							glyphs, num_glyphs,
2070
					       glyphs, num_glyphs,
2046
							NULL, 0, 0,
2071
					       NULL, 0, 0,
2047
							transformed_glyphs,
2072
					       transformed_glyphs,
2048
							NULL, NULL);
-
 
2049
    if (unlikely (status))
-
 
Line 2050... Line 2073...
2050
	goto CLEANUP_GLYPHS;
2073
					       &num_glyphs, NULL);
2051
 
2074
 
2052
    status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
2075
    status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
Line 2053... Line -...
2053
					    transformed_glyphs, num_glyphs,
-
 
2054
					    path);
2076
					    transformed_glyphs, num_glyphs,
2055
 
2077
					    path);
Line 2056... Line 2078...
2056
  CLEANUP_GLYPHS:
2078
 
2057
    if (transformed_glyphs != stack_transformed_glyphs)
2079
    if (transformed_glyphs != stack_transformed_glyphs)
Line 2091... Line 2113...
2091
 * The result of the transformation is placed in @transformed_glyphs.
2113
 * The result of the transformation is placed in @transformed_glyphs.
2092
 *
2114
 *
2093
 * This also uses information from the scaled font and the surface to
2115
 * This also uses information from the scaled font and the surface to
2094
 * cull/drop glyphs that will not be visible.
2116
 * cull/drop glyphs that will not be visible.
2095
 **/
2117
 **/
2096
static cairo_status_t
2118
static void
2097
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t	*gstate,
2119
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t	*gstate,
2098
                                           const cairo_glyph_t	*glyphs,
2120
                                           const cairo_glyph_t	*glyphs,
2099
                                           int			 num_glyphs,
2121
                                           int			 num_glyphs,
2100
					   const cairo_text_cluster_t	*clusters,
2122
					   const cairo_text_cluster_t	*clusters,
2101
					   int			 num_clusters,
2123
					   int			 num_clusters,
2102
					   cairo_text_cluster_flags_t cluster_flags,
2124
					   cairo_text_cluster_flags_t cluster_flags,
2103
                                           cairo_glyph_t	*transformed_glyphs,
2125
                                           cairo_glyph_t	*transformed_glyphs,
2104
					   int			*num_transformed_glyphs,
2126
					   int			*num_transformed_glyphs,
2105
					   cairo_text_cluster_t *transformed_clusters)
2127
					   cairo_text_cluster_t *transformed_clusters)
2106
{
2128
{
2107
    int i, j, k;
2129
    cairo_rectangle_int_t surface_extents;
2108
    cairo_matrix_t *ctm = &gstate->ctm;
2130
    cairo_matrix_t *ctm = &gstate->ctm;
2109
    cairo_matrix_t *font_matrix = &gstate->font_matrix;
2131
    cairo_matrix_t *font_matrix = &gstate->font_matrix;
2110
    cairo_matrix_t *device_transform = &gstate->target->device_transform;
2132
    cairo_matrix_t *device_transform = &gstate->target->device_transform;
2111
    cairo_bool_t drop = FALSE;
2133
    cairo_bool_t drop = FALSE;
2112
    double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
2134
    double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
2113
 
-
 
2114
    if (num_transformed_glyphs != NULL) {
2135
    int i, j, k;
2115
	cairo_rectangle_int_t surface_extents;
-
 
Line 2116... Line 2136...
2116
 
2136
 
2117
	drop = TRUE;
2137
    drop = TRUE;
2118
	if (! _cairo_gstate_int_clip_extents (gstate, &surface_extents)) {
2138
    if (! _cairo_gstate_int_clip_extents (gstate, &surface_extents)) {
2119
	    drop = FALSE; /* unbounded surface */
2139
	drop = FALSE; /* unbounded surface */
2120
	} else {
2140
    } else {
2121
	    double scale10 = 10 * _cairo_scaled_font_get_max_scale (gstate->scaled_font);
2141
	double scale10 = 10 * _cairo_scaled_font_get_max_scale (gstate->scaled_font);
2122
	    if (surface_extents.width == 0 || surface_extents.height == 0) {
2142
	if (surface_extents.width == 0 || surface_extents.height == 0) {
2123
	      /* No visible area.  Don't draw anything */
2143
	  /* No visible area.  Don't draw anything */
2124
	      *num_transformed_glyphs = 0;
2144
	  *num_transformed_glyphs = 0;
2125
	      return CAIRO_STATUS_SUCCESS;
2145
	  return;
2126
	    }
2146
	}
2127
	    /* XXX We currently drop any glyphs that has its position outside
2147
	/* XXX We currently drop any glyphs that has its position outside
2128
	     * of the surface boundaries by a safety margin depending on the
2148
	 * of the surface boundaries by a safety margin depending on the
2129
	     * font scale.  This however can fail in extreme cases where the
2149
	 * font scale.  This however can fail in extreme cases where the
Line 2138... Line 2158...
2138
	    y2 = surface_extents.y + (int) surface_extents.height + scale10;
2158
	y2 = surface_extents.y + (int) surface_extents.height + scale10;
2139
	}
2159
    }
Line 2140... Line 2160...
2140
 
2160
 
2141
	if (!drop)
2161
    if (!drop)
2142
	    *num_transformed_glyphs = num_glyphs;
-
 
2143
    } else
-
 
Line 2144... Line 2162...
2144
	num_transformed_glyphs = &j;
2162
	*num_transformed_glyphs = num_glyphs;
Line 2145... Line 2163...
2145
 
2163
 
2146
#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
2164
#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
Line 2151... Line 2169...
2151
	font_matrix->x0 == 0 && font_matrix->y0 == 0)
2169
	font_matrix->x0 == 0 && font_matrix->y0 == 0)
2152
    {
2170
    {
2153
	if (! drop) {
2171
	if (! drop) {
2154
	    memcpy (transformed_glyphs, glyphs,
2172
	    memcpy (transformed_glyphs, glyphs,
2155
		    num_glyphs * sizeof (cairo_glyph_t));
2173
		    num_glyphs * sizeof (cairo_glyph_t));
-
 
2174
	    memcpy (transformed_clusters, clusters,
-
 
2175
		    num_clusters * sizeof (cairo_text_cluster_t));
2156
	    j = num_glyphs;
2176
	    j = num_glyphs;
2157
	} else if (num_clusters == 0) {
2177
	} else if (num_clusters == 0) {
2158
	    for (i = 0; i < num_glyphs; i++) {
2178
	    for (i = 0; i < num_glyphs; i++) {
2159
		transformed_glyphs[j].index = glyphs[i].index;
2179
		transformed_glyphs[j].index = glyphs[i].index;
2160
		transformed_glyphs[j].x = glyphs[i].x;
2180
		transformed_glyphs[j].x = glyphs[i].x;
Line 2206... Line 2226...
2206
		transformed_glyphs[j].x = glyphs[i].x + tx;
2226
		transformed_glyphs[j].x = glyphs[i].x + tx;
2207
		transformed_glyphs[j].y = glyphs[i].y + ty;
2227
		transformed_glyphs[j].y = glyphs[i].y + ty;
2208
		if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
2228
		if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
2209
		    j++;
2229
		    j++;
2210
	    }
2230
	    }
-
 
2231
	    memcpy (transformed_clusters, clusters,
-
 
2232
		    num_clusters * sizeof (cairo_text_cluster_t));
2211
	} else {
2233
	} else {
2212
	    const cairo_glyph_t *cur_glyph;
2234
	    const cairo_glyph_t *cur_glyph;
Line 2213... Line 2235...
2213
 
2235
 
2214
	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
2236
	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
Line 2259... Line 2281...
2259
					      &transformed_glyphs[j].x,
2281
					      &transformed_glyphs[j].x,
2260
					      &transformed_glyphs[j].y);
2282
					      &transformed_glyphs[j].y);
2261
		if (! drop || KEEP_GLYPH (transformed_glyphs[j]))
2283
		if (! drop || KEEP_GLYPH (transformed_glyphs[j]))
2262
		    j++;
2284
		    j++;
2263
	    }
2285
	    }
-
 
2286
	    memcpy (transformed_clusters, clusters,
-
 
2287
		    num_clusters * sizeof (cairo_text_cluster_t));
2264
	} else {
2288
	} else {
2265
	    const cairo_glyph_t *cur_glyph;
2289
	    const cairo_glyph_t *cur_glyph;
Line 2266... Line 2290...
2266
 
2290
 
2267
	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
2291
	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
Line 2302... Line 2326...
2302
	    tmp = transformed_glyphs[i];
2326
	    tmp = transformed_glyphs[i];
2303
	    transformed_glyphs[i] = transformed_glyphs[j];
2327
	    transformed_glyphs[i] = transformed_glyphs[j];
2304
	    transformed_glyphs[j] = tmp;
2328
	    transformed_glyphs[j] = tmp;
2305
	}
2329
	}
2306
    }
2330
    }
2307
 
-
 
2308
    return CAIRO_STATUS_SUCCESS;
-
 
2309
}
2331
}