Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1892 serge 1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2002 University of Southern California
4
 * Copyright © 2005 Red Hat, Inc.
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 *
29
 * The Original Code is the cairo graphics library.
30
 *
31
 * The Initial Developer of the Original Code is University of Southern
32
 * California.
33
 *
34
 * Contributor(s):
35
 *	Carl D. Worth 
36
 */
37
 
38
#include "cairoint.h"
39
 
3959 Serge 40
#include "cairo-clip-inline.h"
1892 serge 41
#include "cairo-clip-private.h"
42
#include "cairo-error-private.h"
3959 Serge 43
#include "cairo-list-inline.h"
1892 serge 44
#include "cairo-gstate-private.h"
3959 Serge 45
#include "cairo-pattern-private.h"
46
#include "cairo-traps-private.h"
1892 serge 47
 
48
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
49
#define ISFINITE(x) isfinite (x)
50
#else
51
#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
52
#endif
53
 
54
static cairo_status_t
55
_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
56
 
57
static cairo_status_t
58
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
59
 
60
static cairo_status_t
61
_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
62
 
63
static void
64
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
65
 
3959 Serge 66
static void
1892 serge 67
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
68
                                           const cairo_glyph_t *glyphs,
69
                                           int                  num_glyphs,
70
					   const cairo_text_cluster_t	*clusters,
71
					   int			 num_clusters,
72
					   cairo_text_cluster_flags_t cluster_flags,
73
                                           cairo_glyph_t       *transformed_glyphs,
74
					   int			*num_transformed_glyphs,
75
					   cairo_text_cluster_t *transformed_clusters);
76
 
77
static void
78
_cairo_gstate_update_device_transform (cairo_observer_t *observer,
79
				       void *arg)
80
{
81
    cairo_gstate_t *gstate = cairo_container_of (observer,
82
						 cairo_gstate_t,
83
						 device_transform_observer);
84
 
85
    gstate->is_identity = (_cairo_matrix_is_identity (&gstate->ctm) &&
86
			   _cairo_matrix_is_identity (&gstate->target->device_transform));
87
}
88
 
89
cairo_status_t
90
_cairo_gstate_init (cairo_gstate_t  *gstate,
91
		    cairo_surface_t *target)
92
{
93
    VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
94
 
95
    gstate->next = NULL;
96
 
97
    gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
3959 Serge 98
    gstate->opacity = 1.;
1892 serge 99
 
100
    gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
101
    gstate->antialias = CAIRO_ANTIALIAS_DEFAULT;
102
 
103
    _cairo_stroke_style_init (&gstate->stroke_style);
104
 
105
    gstate->fill_rule = CAIRO_GSTATE_FILL_RULE_DEFAULT;
106
 
107
    gstate->font_face = NULL;
108
    gstate->scaled_font = NULL;
109
    gstate->previous_scaled_font = NULL;
110
 
111
    cairo_matrix_init_scale (&gstate->font_matrix,
112
			     CAIRO_GSTATE_DEFAULT_FONT_SIZE,
113
			     CAIRO_GSTATE_DEFAULT_FONT_SIZE);
114
 
115
    _cairo_font_options_init_default (&gstate->font_options);
116
 
3959 Serge 117
    gstate->clip = NULL;
1892 serge 118
 
119
    gstate->target = cairo_surface_reference (target);
120
    gstate->parent_target = NULL;
121
    gstate->original_target = cairo_surface_reference (target);
122
 
123
    gstate->device_transform_observer.callback = _cairo_gstate_update_device_transform;
124
    cairo_list_add (&gstate->device_transform_observer.link,
125
		    &gstate->target->device_transform_observers);
126
 
127
    gstate->is_identity = _cairo_matrix_is_identity (&gstate->target->device_transform);
128
    cairo_matrix_init_identity (&gstate->ctm);
129
    gstate->ctm_inverse = gstate->ctm;
130
    gstate->source_ctm_inverse = gstate->ctm;
131
 
132
    gstate->source = (cairo_pattern_t *) &_cairo_pattern_black.base;
133
 
134
    /* Now that the gstate is fully initialized and ready for the eventual
135
     * _cairo_gstate_fini(), we can check for errors (and not worry about
136
     * the resource deallocation). */
3959 Serge 137
    return target->status;
1892 serge 138
}
139
 
140
/**
141
 * _cairo_gstate_init_copy:
142
 *
143
 * Initialize @gstate by performing a deep copy of state fields from
144
 * @other. Note that gstate->next is not copied but is set to %NULL by
145
 * this function.
146
 **/
147
static cairo_status_t
148
_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
149
{
150
    cairo_status_t status;
151
 
152
    VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
153
 
154
    gstate->op = other->op;
3959 Serge 155
    gstate->opacity = other->opacity;
1892 serge 156
 
157
    gstate->tolerance = other->tolerance;
158
    gstate->antialias = other->antialias;
159
 
160
    status = _cairo_stroke_style_init_copy (&gstate->stroke_style,
161
					    &other->stroke_style);
162
    if (unlikely (status))
163
	return status;
164
 
165
    gstate->fill_rule = other->fill_rule;
166
 
167
    gstate->font_face = cairo_font_face_reference (other->font_face);
168
    gstate->scaled_font = cairo_scaled_font_reference (other->scaled_font);
169
    gstate->previous_scaled_font = cairo_scaled_font_reference (other->previous_scaled_font);
170
 
171
    gstate->font_matrix = other->font_matrix;
172
 
173
    _cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
174
 
3959 Serge 175
    gstate->clip = _cairo_clip_copy (other->clip);
1892 serge 176
 
177
    gstate->target = cairo_surface_reference (other->target);
178
    /* parent_target is always set to NULL; it's only ever set by redirect_target */
179
    gstate->parent_target = NULL;
180
    gstate->original_target = cairo_surface_reference (other->original_target);
181
 
182
    gstate->device_transform_observer.callback = _cairo_gstate_update_device_transform;
183
    cairo_list_add (&gstate->device_transform_observer.link,
184
		    &gstate->target->device_transform_observers);
185
 
186
    gstate->is_identity = other->is_identity;
187
    gstate->ctm = other->ctm;
188
    gstate->ctm_inverse = other->ctm_inverse;
189
    gstate->source_ctm_inverse = other->source_ctm_inverse;
190
 
191
    gstate->source = cairo_pattern_reference (other->source);
192
 
193
    gstate->next = NULL;
194
 
195
    return CAIRO_STATUS_SUCCESS;
196
}
197
 
198
void
199
_cairo_gstate_fini (cairo_gstate_t *gstate)
200
{
201
    _cairo_stroke_style_fini (&gstate->stroke_style);
202
 
203
    cairo_font_face_destroy (gstate->font_face);
204
    gstate->font_face = NULL;
205
 
206
    cairo_scaled_font_destroy (gstate->previous_scaled_font);
207
    gstate->previous_scaled_font = NULL;
208
 
209
    cairo_scaled_font_destroy (gstate->scaled_font);
210
    gstate->scaled_font = NULL;
211
 
3959 Serge 212
    _cairo_clip_destroy (gstate->clip);
1892 serge 213
 
214
    cairo_list_del (&gstate->device_transform_observer.link);
215
 
216
    cairo_surface_destroy (gstate->target);
217
    gstate->target = NULL;
218
 
219
    cairo_surface_destroy (gstate->parent_target);
220
    gstate->parent_target = NULL;
221
 
222
    cairo_surface_destroy (gstate->original_target);
223
    gstate->original_target = NULL;
224
 
225
    cairo_pattern_destroy (gstate->source);
226
    gstate->source = NULL;
227
 
228
    VG (VALGRIND_MAKE_MEM_NOACCESS (gstate, sizeof (cairo_gstate_t)));
229
}
230
 
231
/**
232
 * _cairo_gstate_save:
233
 * @gstate: input/output gstate pointer
234
 *
235
 * Makes a copy of the current state of @gstate and saves it
236
 * to @gstate->next, then put the address of the newly allcated
237
 * copy into @gstate.  _cairo_gstate_restore() reverses this.
238
 **/
239
cairo_status_t
240
_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
241
{
242
    cairo_gstate_t *top;
243
    cairo_status_t status;
244
 
245
    if (CAIRO_INJECT_FAULT ())
246
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
247
 
248
    top = *freelist;
249
    if (top == NULL) {
250
	top = malloc (sizeof (cairo_gstate_t));
251
	if (unlikely (top == NULL))
252
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
253
    } else
254
	*freelist = top->next;
255
 
256
    status = _cairo_gstate_init_copy (top, *gstate);
257
    if (unlikely (status)) {
258
	top->next = *freelist;
259
	*freelist = top;
260
	return status;
261
    }
262
 
263
    top->next = *gstate;
264
    *gstate = top;
265
 
266
    return CAIRO_STATUS_SUCCESS;
267
}
268
 
269
/**
270
 * _cairo_gstate_restore:
271
 * @gstate: input/output gstate pointer
272
 *
273
 * Reverses the effects of one _cairo_gstate_save() call.
274
 **/
275
cairo_status_t
276
_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
277
{
278
    cairo_gstate_t *top;
279
 
280
    top = *gstate;
281
    if (top->next == NULL)
282
	return _cairo_error (CAIRO_STATUS_INVALID_RESTORE);
283
 
284
    *gstate = top->next;
285
 
286
    _cairo_gstate_fini (top);
287
    VG (VALGRIND_MAKE_MEM_UNDEFINED (&top->next, sizeof (cairo_gstate_t *)));
288
    top->next = *freelist;
289
    *freelist = top;
290
 
291
    return CAIRO_STATUS_SUCCESS;
292
}
293
 
294
/**
295
 * _cairo_gstate_redirect_target:
296
 * @gstate: a #cairo_gstate_t
297
 * @child: the new child target
298
 *
299
 * Redirect @gstate rendering to a "child" target. The original
300
 * "parent" target with which the gstate was created will not be
301
 * affected. See _cairo_gstate_get_target().
302
 **/
303
cairo_status_t
304
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
305
{
306
    /* If this gstate is already redirected, this is an error; we need a
307
     * new gstate to be able to redirect */
308
    assert (gstate->parent_target == NULL);
309
 
310
    /* Set up our new parent_target based on our current target;
311
     * gstate->parent_target will take the ref that is held by gstate->target
312
     */
313
    gstate->parent_target = gstate->target;
314
 
315
    /* Now set up our new target; we overwrite gstate->target directly,
316
     * since its ref is now owned by gstate->parent_target */
317
    gstate->target = cairo_surface_reference (child);
318
    gstate->is_identity &= _cairo_matrix_is_identity (&child->device_transform);
319
    cairo_list_move (&gstate->device_transform_observer.link,
320
		     &gstate->target->device_transform_observers);
321
 
322
    /* The clip is in surface backend coordinates for the previous target;
323
     * translate it into the child's backend coordinates. */
3959 Serge 324
    _cairo_clip_destroy (gstate->clip);
325
    gstate->clip = _cairo_clip_copy_with_translation (gstate->next->clip,
326
						      child->device_transform.x0 - gstate->parent_target->device_transform.x0,
327
						      child->device_transform.y0 - gstate->parent_target->device_transform.y0);
328
 
329
    return CAIRO_STATUS_SUCCESS;
1892 serge 330
}
331
 
332
/**
3959 Serge 333
 * _cairo_gstate_is_group:
1892 serge 334
 * @gstate: a #cairo_gstate_t
335
 *
3959 Serge 336
 * Check if _cairo_gstate_redirect_target has been called on the head
337
 * of the stack.
1892 serge 338
 *
3959 Serge 339
 * Return value: %TRUE if @gstate is redirected to a target different
340
 * than the previous state in the stack, %FALSE otherwise.
1892 serge 341
 **/
342
cairo_bool_t
3959 Serge 343
_cairo_gstate_is_group (cairo_gstate_t *gstate)
1892 serge 344
{
3959 Serge 345
    return gstate->parent_target != NULL;
1892 serge 346
}
347
 
348
/**
349
 * _cairo_gstate_get_target:
350
 * @gstate: a #cairo_gstate_t
351
 *
352
 * Return the current drawing target; if drawing is not redirected,
353
 * this will be the same as _cairo_gstate_get_original_target().
354
 *
355
 * Return value: the current target surface
356
 **/
357
cairo_surface_t *
358
_cairo_gstate_get_target (cairo_gstate_t *gstate)
359
{
360
    return gstate->target;
361
}
362
 
363
/**
364
 * _cairo_gstate_get_original_target:
365
 * @gstate: a #cairo_gstate_t
366
 *
367
 * Return the original target with which @gstate was created. This
368
 * function always returns the original target independent of any
369
 * child target that may have been set with
370
 * _cairo_gstate_redirect_target.
371
 *
372
 * Return value: the original target surface
373
 **/
374
cairo_surface_t *
375
_cairo_gstate_get_original_target (cairo_gstate_t *gstate)
376
{
377
    return gstate->original_target;
378
}
379
 
380
/**
381
 * _cairo_gstate_get_clip:
382
 * @gstate: a #cairo_gstate_t
383
 *
384
 * This space left intentionally blank.
385
 *
386
 * Return value: a pointer to the gstate's #cairo_clip_t structure.
3959 Serge 387
 **/
1892 serge 388
cairo_clip_t *
389
_cairo_gstate_get_clip (cairo_gstate_t *gstate)
390
{
3959 Serge 391
    return gstate->clip;
1892 serge 392
}
393
 
394
cairo_status_t
395
_cairo_gstate_set_source (cairo_gstate_t  *gstate,
396
			  cairo_pattern_t *source)
397
{
398
    if (source->status)
399
	return source->status;
400
 
401
    source = cairo_pattern_reference (source);
402
    cairo_pattern_destroy (gstate->source);
403
    gstate->source = source;
404
    gstate->source_ctm_inverse = gstate->ctm_inverse;
405
 
406
    return CAIRO_STATUS_SUCCESS;
407
}
408
 
409
cairo_pattern_t *
410
_cairo_gstate_get_source (cairo_gstate_t *gstate)
411
{
412
    if (gstate->source == &_cairo_pattern_black.base) {
413
	/* do not expose the static object to the user */
414
        gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
415
    }
416
 
417
    return gstate->source;
418
}
419
 
420
cairo_status_t
421
_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t op)
422
{
423
    gstate->op = op;
424
 
425
    return CAIRO_STATUS_SUCCESS;
426
}
427
 
428
cairo_operator_t
429
_cairo_gstate_get_operator (cairo_gstate_t *gstate)
430
{
431
    return gstate->op;
432
}
433
 
434
cairo_status_t
3959 Serge 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
 
448
cairo_status_t
1892 serge 449
_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance)
450
{
451
    gstate->tolerance = tolerance;
452
 
453
    return CAIRO_STATUS_SUCCESS;
454
}
455
 
456
double
457
_cairo_gstate_get_tolerance (cairo_gstate_t *gstate)
458
{
459
    return gstate->tolerance;
460
}
461
 
462
cairo_status_t
463
_cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule)
464
{
465
    gstate->fill_rule = fill_rule;
466
 
467
    return CAIRO_STATUS_SUCCESS;
468
}
469
 
470
cairo_fill_rule_t
471
_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate)
472
{
473
    return gstate->fill_rule;
474
}
475
 
476
cairo_status_t
477
_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width)
478
{
479
    gstate->stroke_style.line_width = width;
480
 
481
    return CAIRO_STATUS_SUCCESS;
482
}
483
 
484
double
485
_cairo_gstate_get_line_width (cairo_gstate_t *gstate)
486
{
487
    return gstate->stroke_style.line_width;
488
}
489
 
490
cairo_status_t
491
_cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap)
492
{
493
    gstate->stroke_style.line_cap = line_cap;
494
 
495
    return CAIRO_STATUS_SUCCESS;
496
}
497
 
498
cairo_line_cap_t
499
_cairo_gstate_get_line_cap (cairo_gstate_t *gstate)
500
{
501
    return gstate->stroke_style.line_cap;
502
}
503
 
504
cairo_status_t
505
_cairo_gstate_set_line_join (cairo_gstate_t *gstate, cairo_line_join_t line_join)
506
{
507
    gstate->stroke_style.line_join = line_join;
508
 
509
    return CAIRO_STATUS_SUCCESS;
510
}
511
 
512
cairo_line_join_t
513
_cairo_gstate_get_line_join (cairo_gstate_t *gstate)
514
{
515
    return gstate->stroke_style.line_join;
516
}
517
 
518
cairo_status_t
519
_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset)
520
{
3959 Serge 521
    double dash_total, on_total, off_total;
522
    int i, j;
1892 serge 523
 
3959 Serge 524
    free (gstate->stroke_style.dash);
1892 serge 525
 
526
    gstate->stroke_style.num_dashes = num_dashes;
527
 
528
    if (gstate->stroke_style.num_dashes == 0) {
529
	gstate->stroke_style.dash = NULL;
530
	gstate->stroke_style.dash_offset = 0.0;
531
	return CAIRO_STATUS_SUCCESS;
532
    }
533
 
534
    gstate->stroke_style.dash = _cairo_malloc_ab (gstate->stroke_style.num_dashes, sizeof (double));
535
    if (unlikely (gstate->stroke_style.dash == NULL)) {
536
	gstate->stroke_style.num_dashes = 0;
537
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
538
    }
539
 
3959 Serge 540
    on_total = off_total = dash_total = 0.0;
541
    for (i = j = 0; i < num_dashes; i++) {
542
	if (dash[i] < 0)
1892 serge 543
	    return _cairo_error (CAIRO_STATUS_INVALID_DASH);
544
 
3959 Serge 545
	if (dash[i] == 0 && i > 0 && i < num_dashes - 1) {
546
	    if (dash[++i] < 0)
547
		return _cairo_error (CAIRO_STATUS_INVALID_DASH);
548
 
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];
558
	    else
559
		off_total += dash[i];
560
	}
1892 serge 561
    }
562
 
563
    if (dash_total == 0.0)
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. */
3959 Serge 568
    if (gstate->stroke_style.num_dashes & 1) {
1892 serge 569
	dash_total *= 2;
3959 Serge 570
	on_total += off_total;
571
    }
1892 serge 572
 
3959 Serge 573
    if (dash_total - on_total < CAIRO_FIXED_ERROR_DOUBLE) {
574
	/* Degenerate dash -> solid line */
575
	free (gstate->stroke_style.dash);
576
	gstate->stroke_style.dash = NULL;
577
	gstate->stroke_style.num_dashes = 0;
578
	gstate->stroke_style.dash_offset = 0.0;
579
	return CAIRO_STATUS_SUCCESS;
580
    }
581
 
1892 serge 582
    /* The dashing code doesn't like a negative offset or a big positive
583
     * offset, so we compute an equivalent offset which is guaranteed to be
584
     * positive and less than twice the pattern length. */
585
    offset = fmod (offset, dash_total);
586
    if (offset < 0.0)
587
	offset += dash_total;
588
    if (offset <= 0.0)		/* Take care of -0 */
589
	offset = 0.0;
590
    gstate->stroke_style.dash_offset = offset;
591
 
592
    return CAIRO_STATUS_SUCCESS;
593
}
594
 
595
void
596
_cairo_gstate_get_dash (cairo_gstate_t *gstate,
597
			double         *dashes,
598
			int            *num_dashes,
599
			double         *offset)
600
{
601
    if (dashes) {
602
	memcpy (dashes,
603
		gstate->stroke_style.dash,
604
		sizeof (double) * gstate->stroke_style.num_dashes);
605
    }
606
 
607
    if (num_dashes)
608
	*num_dashes = gstate->stroke_style.num_dashes;
609
 
610
    if (offset)
611
	*offset = gstate->stroke_style.dash_offset;
612
}
613
 
614
cairo_status_t
615
_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit)
616
{
617
    gstate->stroke_style.miter_limit = limit;
618
 
619
    return CAIRO_STATUS_SUCCESS;
620
}
621
 
622
double
623
_cairo_gstate_get_miter_limit (cairo_gstate_t *gstate)
624
{
625
    return gstate->stroke_style.miter_limit;
626
}
627
 
628
void
629
_cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix)
630
{
631
    *matrix = gstate->ctm;
632
}
633
 
634
cairo_status_t
635
_cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
636
{
637
    cairo_matrix_t tmp;
638
 
639
    if (! ISFINITE (tx) || ! ISFINITE (ty))
640
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
641
 
642
    _cairo_gstate_unset_scaled_font (gstate);
643
 
644
    cairo_matrix_init_translate (&tmp, tx, ty);
645
    cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
646
    gstate->is_identity = FALSE;
647
 
648
    /* paranoid check against gradual numerical instability */
649
    if (! _cairo_matrix_is_invertible (&gstate->ctm))
650
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
651
 
652
    cairo_matrix_init_translate (&tmp, -tx, -ty);
653
    cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
654
 
655
    return CAIRO_STATUS_SUCCESS;
656
}
657
 
658
cairo_status_t
659
_cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
660
{
661
    cairo_matrix_t tmp;
662
 
663
    if (sx * sy == 0.) /* either sx or sy is 0, or det == 0 due to underflow */
664
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
665
    if (! ISFINITE (sx) || ! ISFINITE (sy))
666
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
667
 
668
    _cairo_gstate_unset_scaled_font (gstate);
669
 
670
    cairo_matrix_init_scale (&tmp, sx, sy);
671
    cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
672
    gstate->is_identity = FALSE;
673
 
674
    /* paranoid check against gradual numerical instability */
675
    if (! _cairo_matrix_is_invertible (&gstate->ctm))
676
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
677
 
678
    cairo_matrix_init_scale (&tmp, 1/sx, 1/sy);
679
    cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
680
 
681
    return CAIRO_STATUS_SUCCESS;
682
}
683
 
684
cairo_status_t
685
_cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
686
{
687
    cairo_matrix_t tmp;
688
 
689
    if (angle == 0.)
690
	return CAIRO_STATUS_SUCCESS;
691
 
692
    if (! ISFINITE (angle))
693
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
694
 
695
    _cairo_gstate_unset_scaled_font (gstate);
696
 
697
    cairo_matrix_init_rotate (&tmp, angle);
698
    cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
699
    gstate->is_identity = FALSE;
700
 
701
    /* paranoid check against gradual numerical instability */
702
    if (! _cairo_matrix_is_invertible (&gstate->ctm))
703
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
704
 
705
    cairo_matrix_init_rotate (&tmp, -angle);
706
    cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
707
 
708
    return CAIRO_STATUS_SUCCESS;
709
}
710
 
711
cairo_status_t
712
_cairo_gstate_transform (cairo_gstate_t	      *gstate,
713
			 const cairo_matrix_t *matrix)
714
{
715
    cairo_matrix_t tmp;
716
    cairo_status_t status;
717
 
718
    if (! _cairo_matrix_is_invertible (matrix))
719
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
720
 
721
    if (_cairo_matrix_is_identity (matrix))
722
	return CAIRO_STATUS_SUCCESS;
723
 
724
    tmp = *matrix;
725
    status = cairo_matrix_invert (&tmp);
726
    if (unlikely (status))
727
	return status;
728
 
729
    _cairo_gstate_unset_scaled_font (gstate);
730
 
731
    cairo_matrix_multiply (&gstate->ctm, matrix, &gstate->ctm);
732
    cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
733
    gstate->is_identity = FALSE;
734
 
735
    /* paranoid check against gradual numerical instability */
736
    if (! _cairo_matrix_is_invertible (&gstate->ctm))
737
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
738
 
739
    return CAIRO_STATUS_SUCCESS;
740
}
741
 
742
cairo_status_t
743
_cairo_gstate_set_matrix (cairo_gstate_t       *gstate,
744
			  const cairo_matrix_t *matrix)
745
{
746
    cairo_status_t status;
747
 
748
    if (memcmp (matrix, &gstate->ctm, sizeof (cairo_matrix_t)) == 0)
749
	return CAIRO_STATUS_SUCCESS;
750
 
751
    if (! _cairo_matrix_is_invertible (matrix))
752
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
753
 
754
    if (_cairo_matrix_is_identity (matrix)) {
755
	_cairo_gstate_identity_matrix (gstate);
756
	return CAIRO_STATUS_SUCCESS;
757
    }
758
 
759
    _cairo_gstate_unset_scaled_font (gstate);
760
 
761
    gstate->ctm = *matrix;
762
    gstate->ctm_inverse = *matrix;
763
    status = cairo_matrix_invert (&gstate->ctm_inverse);
764
    assert (status == CAIRO_STATUS_SUCCESS);
765
    gstate->is_identity = FALSE;
766
 
767
    return CAIRO_STATUS_SUCCESS;
768
}
769
 
770
void
771
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
772
{
773
    if (_cairo_matrix_is_identity (&gstate->ctm))
774
	return;
775
 
776
    _cairo_gstate_unset_scaled_font (gstate);
777
 
778
    cairo_matrix_init_identity (&gstate->ctm);
779
    cairo_matrix_init_identity (&gstate->ctm_inverse);
780
    gstate->is_identity = _cairo_matrix_is_identity (&gstate->target->device_transform);
781
}
782
 
783
void
784
_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y)
785
{
786
    cairo_matrix_transform_point (&gstate->ctm, x, y);
787
}
788
 
789
void
790
_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate,
791
				       double *dx, double *dy)
792
{
793
    cairo_matrix_transform_distance (&gstate->ctm, dx, dy);
794
}
795
 
796
void
797
_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y)
798
{
799
    cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
800
}
801
 
802
void
803
_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate,
804
				       double *dx, double *dy)
805
{
806
    cairo_matrix_transform_distance (&gstate->ctm_inverse, dx, dy);
807
}
808
 
809
void
810
_do_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
811
{
812
    cairo_matrix_transform_point (&gstate->ctm, x, y);
813
    cairo_matrix_transform_point (&gstate->target->device_transform, x, y);
814
}
815
 
816
void
3959 Serge 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
 
823
void
1892 serge 824
_do_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
825
{
826
    cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y);
827
    cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
828
}
829
 
830
void
3959 Serge 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
}
836
 
837
void
1892 serge 838
_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
839
                                         double *x1, double *y1,
840
                                         double *x2, double *y2,
841
                                         cairo_bool_t *is_tight)
842
{
843
    cairo_matrix_t matrix_inverse;
844
 
3959 Serge 845
    if (! _cairo_matrix_is_identity (&gstate->target->device_transform_inverse) ||
846
    ! _cairo_matrix_is_identity (&gstate->ctm_inverse))
847
    {
848
	cairo_matrix_multiply (&matrix_inverse,
849
			       &gstate->target->device_transform_inverse,
850
			       &gstate->ctm_inverse);
851
	_cairo_matrix_transform_bounding_box (&matrix_inverse,
852
					      x1, y1, x2, y2, is_tight);
853
    }
854
 
855
    else
856
    {
857
	if (is_tight)
858
	    *is_tight = TRUE;
859
    }
1892 serge 860
}
861
 
862
/* XXX: NYI
863
cairo_status_t
864
_cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
865
{
866
    cairo_status_t status;
867
 
868
    _cairo_pen_init (&gstate);
869
    return CAIRO_STATUS_SUCCESS;
870
}
871
*/
872
 
873
void
874
_cairo_gstate_path_extents (cairo_gstate_t     *gstate,
875
			    cairo_path_fixed_t *path,
876
			    double *x1, double *y1,
877
			    double *x2, double *y2)
878
{
879
    cairo_box_t box;
880
    double px1, py1, px2, py2;
881
 
882
    if (_cairo_path_fixed_extents (path, &box)) {
883
	px1 = _cairo_fixed_to_double (box.p1.x);
884
	py1 = _cairo_fixed_to_double (box.p1.y);
885
	px2 = _cairo_fixed_to_double (box.p2.x);
886
	py2 = _cairo_fixed_to_double (box.p2.y);
887
 
888
	_cairo_gstate_backend_to_user_rectangle (gstate,
889
						 &px1, &py1, &px2, &py2,
890
						 NULL);
891
    } else {
892
	px1 = 0.0;
893
	py1 = 0.0;
894
	px2 = 0.0;
895
	py2 = 0.0;
896
    }
897
 
898
    if (x1)
899
	*x1 = px1;
900
    if (y1)
901
	*y1 = py1;
902
    if (x2)
903
	*x2 = px2;
904
    if (y2)
905
	*y2 = py2;
906
}
907
 
908
static void
909
_cairo_gstate_copy_pattern (cairo_pattern_t *pattern,
910
			    const cairo_pattern_t *original)
911
{
912
    /* First check if the we can replace the original with a much simpler
913
     * pattern. For example, gradients that are uniform or just have a single
914
     * stop can sometimes be replaced with a solid.
915
     */
916
 
917
    if (_cairo_pattern_is_clear (original)) {
918
        _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
919
				   CAIRO_COLOR_TRANSPARENT);
920
	return;
921
    }
922
 
923
    if (original->type == CAIRO_PATTERN_TYPE_LINEAR ||
924
	original->type == CAIRO_PATTERN_TYPE_RADIAL)
925
    {
926
        cairo_color_t color;
927
	if (_cairo_gradient_pattern_is_solid ((cairo_gradient_pattern_t *) original,
928
					      NULL,
929
					      &color))
930
	{
931
	    _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
932
				       &color);
933
	    return;
934
	}
935
    }
936
 
937
    _cairo_pattern_init_static_copy (pattern, original);
938
}
939
 
940
static void
941
_cairo_gstate_copy_transformed_pattern (cairo_gstate_t  *gstate,
942
					cairo_pattern_t *pattern,
943
					const cairo_pattern_t *original,
944
					const cairo_matrix_t  *ctm_inverse)
945
{
946
    _cairo_gstate_copy_pattern (pattern, original);
947
 
948
    /* apply device_transform first so that it is transformed by ctm_inverse */
949
    if (original->type == CAIRO_PATTERN_TYPE_SURFACE) {
950
	cairo_surface_pattern_t *surface_pattern;
951
	cairo_surface_t *surface;
952
 
953
        surface_pattern = (cairo_surface_pattern_t *) original;
954
        surface = surface_pattern->surface;
955
 
956
	if (_cairo_surface_has_device_transform (surface))
957
	    _cairo_pattern_transform (pattern, &surface->device_transform);
958
    }
959
 
960
    if (! _cairo_matrix_is_identity (ctm_inverse))
961
	_cairo_pattern_transform (pattern, ctm_inverse);
962
 
963
    if (_cairo_surface_has_device_transform (gstate->target)) {
964
        _cairo_pattern_transform (pattern,
965
                                  &gstate->target->device_transform_inverse);
966
    }
967
}
968
 
969
static void
970
_cairo_gstate_copy_transformed_source (cairo_gstate_t   *gstate,
971
				       cairo_pattern_t  *pattern)
972
{
973
    _cairo_gstate_copy_transformed_pattern (gstate, pattern,
974
					    gstate->source,
975
					    &gstate->source_ctm_inverse);
976
}
977
 
978
static void
979
_cairo_gstate_copy_transformed_mask (cairo_gstate_t   *gstate,
980
				     cairo_pattern_t  *pattern,
981
				     cairo_pattern_t  *mask)
982
{
983
    _cairo_gstate_copy_transformed_pattern (gstate, pattern,
984
					    mask,
985
					    &gstate->ctm_inverse);
986
}
987
 
988
static cairo_operator_t
989
_reduce_op (cairo_gstate_t *gstate)
990
{
991
    cairo_operator_t op;
992
    const cairo_pattern_t *pattern;
993
 
994
    op = gstate->op;
995
    if (op != CAIRO_OPERATOR_SOURCE)
996
	return op;
997
 
998
    pattern = gstate->source;
999
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1000
	const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
1001
	if (solid->color.alpha_short <= 0x00ff) {
1002
	    op = CAIRO_OPERATOR_CLEAR;
1003
	} else if ((gstate->target->content & CAIRO_CONTENT_ALPHA) == 0) {
1004
	    if ((solid->color.red_short |
1005
		 solid->color.green_short |
1006
		 solid->color.blue_short) <= 0x00ff)
1007
	    {
1008
		op = CAIRO_OPERATOR_CLEAR;
1009
	    }
1010
	}
1011
    } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
1012
	const cairo_surface_pattern_t *surface = (cairo_surface_pattern_t *) pattern;
1013
	if (surface->surface->is_clear &&
1014
	    surface->surface->content & CAIRO_CONTENT_ALPHA)
1015
	{
1016
	    op = CAIRO_OPERATOR_CLEAR;
1017
	}
1018
    } else {
1019
	const cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
1020
	if (gradient->n_stops == 0)
1021
	    op = CAIRO_OPERATOR_CLEAR;
1022
    }
1023
 
1024
    return op;
1025
}
1026
 
3959 Serge 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;
1039
}
1040
 
1892 serge 1041
cairo_status_t
1042
_cairo_gstate_paint (cairo_gstate_t *gstate)
1043
{
1044
    cairo_pattern_union_t source_pattern;
1045
    const cairo_pattern_t *pattern;
1046
    cairo_status_t status;
1047
    cairo_operator_t op;
1048
 
3959 Serge 1049
    status = _cairo_gstate_get_pattern_status (gstate->source);
1050
    if (unlikely (status))
1051
	return status;
1892 serge 1052
 
1053
    if (gstate->op == CAIRO_OPERATOR_DEST)
1054
	return CAIRO_STATUS_SUCCESS;
1055
 
3959 Serge 1056
    if (_cairo_clip_is_all_clipped (gstate->clip))
1892 serge 1057
	return CAIRO_STATUS_SUCCESS;
1058
 
1059
    op = _reduce_op (gstate);
1060
    if (op == CAIRO_OPERATOR_CLEAR) {
1061
	pattern = &_cairo_pattern_clear.base;
1062
    } else {
1063
	_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
1064
	pattern = &source_pattern.base;
1065
    }
1066
 
3959 Serge 1067
    return _cairo_surface_paint (gstate->target,
1068
				 op, pattern,
1069
				 gstate->clip);
1892 serge 1070
}
1071
 
1072
cairo_status_t
1073
_cairo_gstate_mask (cairo_gstate_t  *gstate,
1074
		    cairo_pattern_t *mask)
1075
{
1076
    cairo_pattern_union_t source_pattern, mask_pattern;
1077
    const cairo_pattern_t *source;
1078
    cairo_operator_t op;
1079
    cairo_status_t status;
1080
 
3959 Serge 1081
    status = _cairo_gstate_get_pattern_status (mask);
1082
    if (unlikely (status))
1083
	return status;
1892 serge 1084
 
3959 Serge 1085
    status = _cairo_gstate_get_pattern_status (gstate->source);
1086
    if (unlikely (status))
1087
	return status;
1892 serge 1088
 
1089
    if (gstate->op == CAIRO_OPERATOR_DEST)
1090
	return CAIRO_STATUS_SUCCESS;
1091
 
3959 Serge 1092
    if (_cairo_clip_is_all_clipped (gstate->clip))
1892 serge 1093
	return CAIRO_STATUS_SUCCESS;
1094
 
3959 Serge 1095
    assert (gstate->opacity == 1.0);
1096
 
1892 serge 1097
    if (_cairo_pattern_is_opaque (mask, NULL))
1098
	return _cairo_gstate_paint (gstate);
1099
 
1100
    if (_cairo_pattern_is_clear (mask) &&
1101
	_cairo_operator_bounded_by_mask (gstate->op))
1102
    {
1103
	return CAIRO_STATUS_SUCCESS;
1104
    }
1105
 
1106
    op = _reduce_op (gstate);
1107
    if (op == CAIRO_OPERATOR_CLEAR) {
1108
	source = &_cairo_pattern_clear.base;
1109
    } else {
1110
	_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
1111
	source = &source_pattern.base;
1112
    }
1113
    _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
1114
 
1115
    if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
3959 Serge 1116
	mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
1892 serge 1117
	_cairo_operator_bounded_by_source (op))
1118
    {
1119
	const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
1120
	cairo_color_t combined;
1121
 
1122
	if (mask_pattern.base.has_component_alpha) {
1123
#define M(R, A, B, c) R.c = A.c * B.c
1124
	    M(combined, solid->color, mask_pattern.solid.color, red);
1125
	    M(combined, solid->color, mask_pattern.solid.color, green);
1126
	    M(combined, solid->color, mask_pattern.solid.color, blue);
1127
	    M(combined, solid->color, mask_pattern.solid.color, alpha);
1128
#undef M
1129
	} else {
1130
	    combined = solid->color;
1131
	    _cairo_color_multiply_alpha (&combined, mask_pattern.solid.color.alpha);
1132
	}
1133
 
1134
	_cairo_pattern_init_solid (&source_pattern.solid, &combined);
1135
 
1136
	status = _cairo_surface_paint (gstate->target, op,
1137
				       &source_pattern.base,
3959 Serge 1138
				       gstate->clip);
1892 serge 1139
    }
1140
    else
1141
    {
1142
	status = _cairo_surface_mask (gstate->target, op,
1143
				      source,
1144
				      &mask_pattern.base,
3959 Serge 1145
				      gstate->clip);
1892 serge 1146
    }
1147
 
1148
    return status;
1149
}
1150
 
1151
cairo_status_t
1152
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1153
{
1154
    cairo_pattern_union_t source_pattern;
1155
    cairo_stroke_style_t style;
1156
    double dash[2];
1157
    cairo_status_t status;
1158
 
3959 Serge 1159
    status = _cairo_gstate_get_pattern_status (gstate->source);
1160
    if (unlikely (status))
1161
	return status;
1892 serge 1162
 
1163
    if (gstate->op == CAIRO_OPERATOR_DEST)
1164
	return CAIRO_STATUS_SUCCESS;
1165
 
1166
    if (gstate->stroke_style.line_width <= 0.0)
1167
	return CAIRO_STATUS_SUCCESS;
1168
 
3959 Serge 1169
    if (_cairo_clip_is_all_clipped (gstate->clip))
1892 serge 1170
	return CAIRO_STATUS_SUCCESS;
1171
 
3959 Serge 1172
    assert (gstate->opacity == 1.0);
1173
 
1892 serge 1174
    memcpy (&style, &gstate->stroke_style, sizeof (gstate->stroke_style));
1175
    if (_cairo_stroke_style_dash_can_approximate (&gstate->stroke_style, &gstate->ctm, gstate->tolerance)) {
1176
        style.dash = dash;
1177
        _cairo_stroke_style_dash_approximate (&gstate->stroke_style, &gstate->ctm, gstate->tolerance,
1178
					      &style.dash_offset,
1179
					      style.dash,
1180
					      &style.num_dashes);
1181
    }
1182
 
1183
    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
1184
 
3959 Serge 1185
    return _cairo_surface_stroke (gstate->target,
1186
				  gstate->op,
1187
				  &source_pattern.base,
1188
				  path,
1189
				  &style,
1190
				  &gstate->ctm,
1191
				  &gstate->ctm_inverse,
1192
				  gstate->tolerance,
1193
				  gstate->antialias,
1194
				  gstate->clip);
1892 serge 1195
}
1196
 
1197
cairo_status_t
1198
_cairo_gstate_in_stroke (cairo_gstate_t	    *gstate,
1199
			 cairo_path_fixed_t *path,
1200
			 double		     x,
1201
			 double		     y,
1202
			 cairo_bool_t	    *inside_ret)
1203
{
1204
    cairo_status_t status;
1205
    cairo_rectangle_int_t extents;
1206
    cairo_box_t limit;
1207
    cairo_traps_t traps;
1208
 
1209
    if (gstate->stroke_style.line_width <= 0.0) {
1210
	*inside_ret = FALSE;
1211
	return CAIRO_STATUS_SUCCESS;
1212
    }
1213
 
1214
    _cairo_gstate_user_to_backend (gstate, &x, &y);
1215
 
1216
    /* Before we perform the expensive stroke analysis,
1217
     * check whether the point is within the extents of the path.
1218
     */
1219
    _cairo_path_fixed_approximate_stroke_extents (path,
1220
						  &gstate->stroke_style,
1221
						  &gstate->ctm,
1222
						  &extents);
1223
    if (x < extents.x || x > extents.x + extents.width ||
1224
	y < extents.y || y > extents.y + extents.height)
1225
    {
1226
	*inside_ret = FALSE;
1227
	return CAIRO_STATUS_SUCCESS;
1228
    }
1229
 
1230
    limit.p1.x = _cairo_fixed_from_double (x) - 1;
1231
    limit.p1.y = _cairo_fixed_from_double (y) - 1;
1232
    limit.p2.x = limit.p1.x + 2;
1233
    limit.p2.y = limit.p1.y + 2;
1234
 
1235
    _cairo_traps_init (&traps);
1236
    _cairo_traps_limit (&traps, &limit, 1);
1237
 
3959 Serge 1238
    status = _cairo_path_fixed_stroke_polygon_to_traps (path,
1239
							&gstate->stroke_style,
1240
							&gstate->ctm,
1241
							&gstate->ctm_inverse,
1242
							gstate->tolerance,
1243
							&traps);
1892 serge 1244
    if (unlikely (status))
1245
	goto BAIL;
1246
 
1247
    *inside_ret = _cairo_traps_contain (&traps, x, y);
1248
 
1249
BAIL:
1250
    _cairo_traps_fini (&traps);
1251
 
1252
    return status;
1253
}
1254
 
1255
cairo_status_t
1256
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1257
{
1258
    cairo_status_t status;
1259
 
3959 Serge 1260
    status = _cairo_gstate_get_pattern_status (gstate->source);
1261
    if (unlikely (status))
1262
	return status;
1892 serge 1263
 
1264
    if (gstate->op == CAIRO_OPERATOR_DEST)
1265
	return CAIRO_STATUS_SUCCESS;
1266
 
3959 Serge 1267
    if (_cairo_clip_is_all_clipped (gstate->clip))
1892 serge 1268
	return CAIRO_STATUS_SUCCESS;
1269
 
3959 Serge 1270
    assert (gstate->opacity == 1.0);
1271
 
1892 serge 1272
    if (_cairo_path_fixed_fill_is_empty (path)) {
1273
	if (_cairo_operator_bounded_by_mask (gstate->op))
1274
	    return CAIRO_STATUS_SUCCESS;
1275
 
1276
	status = _cairo_surface_paint (gstate->target,
1277
				       CAIRO_OPERATOR_CLEAR,
1278
				       &_cairo_pattern_clear.base,
3959 Serge 1279
				       gstate->clip);
1892 serge 1280
    } else {
1281
	cairo_pattern_union_t source_pattern;
1282
	const cairo_pattern_t *pattern;
1283
	cairo_operator_t op;
1284
	cairo_rectangle_int_t extents;
1285
	cairo_box_t box;
1286
 
1287
	op = _reduce_op (gstate);
1288
	if (op == CAIRO_OPERATOR_CLEAR) {
1289
	    pattern = &_cairo_pattern_clear.base;
1290
	} else {
1291
	    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
1292
	    pattern = &source_pattern.base;
1293
	}
1294
 
1295
	/* Toolkits often paint the entire background with a fill */
1296
	if (_cairo_surface_get_extents (gstate->target, &extents) &&
1297
	    _cairo_path_fixed_is_box (path, &box) &&
1298
	    box.p1.x <= _cairo_fixed_from_int (extents.x) &&
1299
	    box.p1.y <= _cairo_fixed_from_int (extents.y) &&
1300
	    box.p2.x >= _cairo_fixed_from_int (extents.x + extents.width) &&
1301
	    box.p2.y >= _cairo_fixed_from_int (extents.y + extents.height))
1302
	{
1303
	    status = _cairo_surface_paint (gstate->target, op, pattern,
3959 Serge 1304
					   gstate->clip);
1892 serge 1305
	}
1306
	else
1307
	{
1308
	    status = _cairo_surface_fill (gstate->target, op, pattern,
1309
					  path,
1310
					  gstate->fill_rule,
1311
					  gstate->tolerance,
1312
					  gstate->antialias,
3959 Serge 1313
					  gstate->clip);
1892 serge 1314
	}
1315
    }
1316
 
1317
    return status;
1318
}
1319
 
1320
cairo_bool_t
1321
_cairo_gstate_in_fill (cairo_gstate_t	  *gstate,
1322
		       cairo_path_fixed_t *path,
1323
		       double		   x,
1324
		       double		   y)
1325
{
1326
    _cairo_gstate_user_to_backend (gstate, &x, &y);
1327
 
1328
    return _cairo_path_fixed_in_fill (path,
1329
				      gstate->fill_rule,
1330
				      gstate->tolerance,
1331
				      x, y);
1332
}
1333
 
1334
cairo_bool_t
1335
_cairo_gstate_in_clip (cairo_gstate_t	  *gstate,
1336
		       double		   x,
1337
		       double		   y)
1338
{
3959 Serge 1339
    cairo_clip_t *clip = gstate->clip;
1340
    int i;
1892 serge 1341
 
3959 Serge 1342
    if (_cairo_clip_is_all_clipped (clip))
1892 serge 1343
	return FALSE;
1344
 
3959 Serge 1345
    if (clip == NULL)
1892 serge 1346
	return TRUE;
1347
 
1348
    _cairo_gstate_user_to_backend (gstate, &x, &y);
1349
 
3959 Serge 1350
    if (x <  clip->extents.x ||
1351
	x >= clip->extents.x + clip->extents.width ||
1352
	y <  clip->extents.y ||
1353
	y >= clip->extents.y + clip->extents.height)
1892 serge 1354
    {
1355
	return FALSE;
1356
    }
1357
 
3959 Serge 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)
1892 serge 1369
	    return FALSE;
3959 Serge 1370
    }
1892 serge 1371
 
3959 Serge 1372
    if (clip->path) {
1373
	cairo_clip_path_t *clip_path = clip->path;
1374
	do {
1375
	    if (! _cairo_path_fixed_in_fill (&clip_path->path,
1376
					     clip_path->fill_rule,
1377
					     clip_path->tolerance,
1378
					     x, y))
1379
		return FALSE;
1380
	} while ((clip_path = clip_path->prev) != NULL);
1381
    }
1382
 
1892 serge 1383
    return TRUE;
1384
}
1385
 
1386
cairo_status_t
1387
_cairo_gstate_copy_page (cairo_gstate_t *gstate)
1388
{
1389
    cairo_surface_copy_page (gstate->target);
1390
    return cairo_surface_status (gstate->target);
1391
}
1392
 
1393
cairo_status_t
1394
_cairo_gstate_show_page (cairo_gstate_t *gstate)
1395
{
1396
    cairo_surface_show_page (gstate->target);
1397
    return cairo_surface_status (gstate->target);
1398
}
1399
 
1400
static void
3959 Serge 1401
_cairo_gstate_extents_to_user_rectangle (cairo_gstate_t	  *gstate,
1402
					 const cairo_box_t *extents,
1403
					 double *x1, double *y1,
1404
					 double *x2, double *y2)
1892 serge 1405
{
3959 Serge 1406
    double px1, py1, px2, py2;
1892 serge 1407
 
3959 Serge 1408
    px1 = _cairo_fixed_to_double (extents->p1.x);
1409
    py1 = _cairo_fixed_to_double (extents->p1.y);
1410
    px2 = _cairo_fixed_to_double (extents->p2.x);
1411
    py2 = _cairo_fixed_to_double (extents->p2.y);
1892 serge 1412
 
3959 Serge 1413
    _cairo_gstate_backend_to_user_rectangle (gstate,
1414
					     &px1, &py1, &px2, &py2,
1415
					     NULL);
1416
    if (x1)
1417
	*x1 = px1;
1418
    if (y1)
1419
	*y1 = py1;
1420
    if (x2)
1421
	*x2 = px2;
1422
    if (y2)
1423
	*y2 = py2;
1892 serge 1424
}
1425
 
1426
cairo_status_t
1427
_cairo_gstate_stroke_extents (cairo_gstate_t	 *gstate,
1428
			      cairo_path_fixed_t *path,
1429
                              double *x1, double *y1,
1430
			      double *x2, double *y2)
1431
{
3959 Serge 1432
    cairo_int_status_t status;
1433
    cairo_box_t extents;
1434
    cairo_bool_t empty;
1892 serge 1435
 
3959 Serge 1436
    if (x1)
1437
	*x1 = 0.0;
1438
    if (y1)
1439
	*y1 = 0.0;
1440
    if (x2)
1441
	*x2 = 0.0;
1442
    if (y2)
1443
	*y2 = 0.0;
1444
 
1445
    if (gstate->stroke_style.line_width <= 0.0)
1892 serge 1446
	return CAIRO_STATUS_SUCCESS;
3959 Serge 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)
1460
	    _cairo_boxes_extents (&boxes, &extents);
1461
	_cairo_boxes_fini (&boxes);
1892 serge 1462
    }
1463
 
3959 Serge 1464
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1465
	cairo_polygon_t polygon;
1892 serge 1466
 
3959 Serge 1467
	_cairo_polygon_init (&polygon, NULL, 0);
1468
	status = _cairo_path_fixed_stroke_to_polygon (path,
1469
						      &gstate->stroke_style,
1470
						      &gstate->ctm,
1471
						      &gstate->ctm_inverse,
1472
						      gstate->tolerance,
1473
						      &polygon);
1474
	empty = polygon.num_edges == 0;
1475
	if (! empty)
1476
	    extents = polygon.extents;
1477
	_cairo_polygon_fini (&polygon);
1892 serge 1478
    }
3959 Serge 1479
    if (! empty) {
1480
	_cairo_gstate_extents_to_user_rectangle (gstate, &extents,
1481
						 x1, y1, x2, y2);
1482
    }
1892 serge 1483
 
1484
    return status;
1485
}
1486
 
1487
cairo_status_t
1488
_cairo_gstate_fill_extents (cairo_gstate_t     *gstate,
1489
			    cairo_path_fixed_t *path,
1490
                            double *x1, double *y1,
1491
			    double *x2, double *y2)
1492
{
1493
    cairo_status_t status;
3959 Serge 1494
    cairo_box_t extents;
1495
    cairo_bool_t empty;
1892 serge 1496
 
3959 Serge 1497
    if (x1)
1498
	*x1 = 0.0;
1499
    if (y1)
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))
1892 serge 1507
	return CAIRO_STATUS_SUCCESS;
1508
 
3959 Serge 1509
    if (_cairo_path_fixed_fill_is_rectilinear (path)) {
1510
	cairo_boxes_t boxes;
1892 serge 1511
 
3959 Serge 1512
	_cairo_boxes_init (&boxes);
1513
	status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
1514
							      gstate->fill_rule,
1515
							      gstate->antialias,
1516
							      &boxes);
1517
	empty = boxes.num_boxes == 0;
1518
	if (! empty)
1519
	    _cairo_boxes_extents (&boxes, &extents);
1520
 
1521
	_cairo_boxes_fini (&boxes);
1522
    } else {
1523
	cairo_traps_t traps;
1524
 
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;
1532
	if (! empty)
1533
	    _cairo_traps_extents (&traps, &extents);
1534
 
1535
	_cairo_traps_fini (&traps);
1892 serge 1536
    }
1537
 
3959 Serge 1538
    if (! empty) {
1539
	_cairo_gstate_extents_to_user_rectangle (gstate, &extents,
1540
						 x1, y1, x2, y2);
1541
    }
1892 serge 1542
 
1543
    return status;
1544
}
1545
 
1546
cairo_status_t
1547
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
1548
{
3959 Serge 1549
    _cairo_clip_destroy (gstate->clip);
1550
    gstate->clip = NULL;
1892 serge 1551
 
1552
    return CAIRO_STATUS_SUCCESS;
1553
}
1554
 
1555
cairo_status_t
1556
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
1557
{
3959 Serge 1558
    gstate->clip =
1559
	_cairo_clip_intersect_path (gstate->clip,
1560
				    path,
1561
				    gstate->fill_rule,
1562
				    gstate->tolerance,
1563
				    gstate->antialias);
1564
    /* XXX */
1565
    return CAIRO_STATUS_SUCCESS;
1892 serge 1566
}
1567
 
1568
static cairo_bool_t
1569
_cairo_gstate_int_clip_extents (cairo_gstate_t        *gstate,
1570
				cairo_rectangle_int_t *extents)
1571
{
1572
    cairo_bool_t is_bounded;
1573
 
1574
    is_bounded = _cairo_surface_get_extents (gstate->target, extents);
1575
 
3959 Serge 1576
    if (gstate->clip) {
1577
	_cairo_rectangle_intersect (extents,
1578
				    _cairo_clip_get_extents (gstate->clip));
1892 serge 1579
	is_bounded = TRUE;
1580
    }
1581
 
1582
    return is_bounded;
1583
}
1584
 
1585
cairo_bool_t
1586
_cairo_gstate_clip_extents (cairo_gstate_t *gstate,
1587
		            double         *x1,
1588
		            double         *y1,
1589
			    double         *x2,
1590
			    double         *y2)
1591
{
1592
    cairo_rectangle_int_t extents;
1593
    double px1, py1, px2, py2;
1594
 
1595
    if (! _cairo_gstate_int_clip_extents (gstate, &extents))
1596
	return FALSE;
1597
 
1598
    px1 = extents.x;
1599
    py1 = extents.y;
1600
    px2 = extents.x + (int) extents.width;
1601
    py2 = extents.y + (int) extents.height;
1602
 
1603
    _cairo_gstate_backend_to_user_rectangle (gstate,
1604
					     &px1, &py1, &px2, &py2,
1605
					     NULL);
1606
 
1607
    if (x1)
1608
	*x1 = px1;
1609
    if (y1)
1610
	*y1 = py1;
1611
    if (x2)
1612
	*x2 = px2;
1613
    if (y2)
1614
	*y2 = py2;
1615
 
1616
    return TRUE;
1617
}
1618
 
1619
cairo_rectangle_list_t*
1620
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
1621
{
1622
    cairo_rectangle_int_t extents;
1623
    cairo_rectangle_list_t *list;
3959 Serge 1624
    cairo_clip_t *clip;
1892 serge 1625
 
1626
    if (_cairo_surface_get_extents (gstate->target, &extents))
3959 Serge 1627
	clip = _cairo_clip_copy_intersect_rectangle (gstate->clip, &extents);
1628
    else
1629
	clip = gstate->clip;
1892 serge 1630
 
3959 Serge 1631
    list = _cairo_clip_copy_rectangle_list (clip, gstate);
1892 serge 1632
 
3959 Serge 1633
    if (clip != gstate->clip)
1634
	_cairo_clip_destroy (clip);
1635
 
1892 serge 1636
    return list;
1637
}
1638
 
1639
static void
1640
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate)
1641
{
1642
    if (gstate->scaled_font == NULL)
1643
	return;
1644
 
1645
    if (gstate->previous_scaled_font != NULL)
1646
	cairo_scaled_font_destroy (gstate->previous_scaled_font);
1647
 
1648
    gstate->previous_scaled_font = gstate->scaled_font;
1649
    gstate->scaled_font = NULL;
1650
}
1651
 
1652
cairo_status_t
1653
_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
1654
			     double          size)
1655
{
1656
    _cairo_gstate_unset_scaled_font (gstate);
1657
 
1658
    cairo_matrix_init_scale (&gstate->font_matrix, size, size);
1659
 
1660
    return CAIRO_STATUS_SUCCESS;
1661
}
1662
 
1663
cairo_status_t
1664
_cairo_gstate_set_font_matrix (cairo_gstate_t	    *gstate,
1665
			       const cairo_matrix_t *matrix)
1666
{
1667
    if (memcmp (matrix, &gstate->font_matrix, sizeof (cairo_matrix_t)) == 0)
1668
	return CAIRO_STATUS_SUCCESS;
1669
 
1670
    _cairo_gstate_unset_scaled_font (gstate);
1671
 
1672
    gstate->font_matrix = *matrix;
1673
 
1674
    return CAIRO_STATUS_SUCCESS;
1675
}
1676
 
1677
void
1678
_cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
1679
			       cairo_matrix_t *matrix)
1680
{
1681
    *matrix = gstate->font_matrix;
1682
}
1683
 
1684
void
1685
_cairo_gstate_set_font_options (cairo_gstate_t             *gstate,
1686
				const cairo_font_options_t *options)
1687
{
1688
    if (memcmp (options, &gstate->font_options, sizeof (cairo_font_options_t)) == 0)
1689
	return;
1690
 
1691
    _cairo_gstate_unset_scaled_font (gstate);
1692
 
1693
    _cairo_font_options_init_copy (&gstate->font_options, options);
1694
}
1695
 
1696
void
1697
_cairo_gstate_get_font_options (cairo_gstate_t       *gstate,
1698
				cairo_font_options_t *options)
1699
{
1700
    *options = gstate->font_options;
1701
}
1702
 
1703
cairo_status_t
1704
_cairo_gstate_get_font_face (cairo_gstate_t     *gstate,
1705
			     cairo_font_face_t **font_face)
1706
{
1707
    cairo_status_t status;
1708
 
1709
    status = _cairo_gstate_ensure_font_face (gstate);
1710
    if (unlikely (status))
1711
	return status;
1712
 
1713
    *font_face = gstate->font_face;
1714
 
1715
    return CAIRO_STATUS_SUCCESS;
1716
}
1717
 
1718
cairo_status_t
1719
_cairo_gstate_get_scaled_font (cairo_gstate_t       *gstate,
1720
			       cairo_scaled_font_t **scaled_font)
1721
{
1722
    cairo_status_t status;
1723
 
1724
    status = _cairo_gstate_ensure_scaled_font (gstate);
1725
    if (unlikely (status))
1726
	return status;
1727
 
1728
    *scaled_font = gstate->scaled_font;
1729
 
1730
    return CAIRO_STATUS_SUCCESS;
1731
}
1732
 
1733
/*
1734
 * Like everything else in this file, fonts involve Too Many Coordinate Spaces;
1735
 * it is easy to get confused about what's going on.
1736
 *
1737
 * The user's view
1738
 * ---------------
1739
 *
1740
 * Users ask for things in user space. When cairo starts, a user space unit
1741
 * is about 1/96 inch, which is similar to (but importantly different from)
1742
 * the normal "point" units most users think in terms of. When a user
1743
 * selects a font, its scale is set to "one user unit". The user can then
1744
 * independently scale the user coordinate system *or* the font matrix, in
1745
 * order to adjust the rendered size of the font.
1746
 *
1747
 * Metrics are returned in user space, whether they are obtained from
1748
 * the currently selected font in a  #cairo_t or from a #cairo_scaled_font_t
1749
 * which is a font specialized to a particular scale matrix, CTM, and target
1750
 * surface.
1751
 *
1752
 * The font's view
1753
 * ---------------
1754
 *
1755
 * Fonts are designed and stored (in say .ttf files) in "font space", which
1756
 * describes an "EM Square" (a design tile) and has some abstract number
1757
 * such as 1000, 1024, or 2048 units per "EM". This is basically an
1758
 * uninteresting space for us, but we need to remember that it exists.
1759
 *
1760
 * Font resources (from libraries or operating systems) render themselves
1761
 * to a particular device. Since they do not want to make most programmers
1762
 * worry about the font design space, the scaling API is simplified to
1763
 * involve just telling the font the required pixel size of the EM square
1764
 * (that is, in device space).
1765
 *
1766
 *
1767
 * Cairo's gstate view
1768
 * -------------------
1769
 *
1770
 * In addition to the CTM and CTM inverse, we keep a matrix in the gstate
1771
 * called the "font matrix" which describes the user's most recent
1772
 * font-scaling or font-transforming request. This is kept in terms of an
1773
 * abstract scale factor, composed with the CTM and used to set the font's
1774
 * pixel size. So if the user asks to "scale the font by 12", the matrix
1775
 * is:
1776
 *
1777
 *   [ 12.0, 0.0, 0.0, 12.0, 0.0, 0.0 ]
1778
 *
1779
 * It is an affine matrix, like all cairo matrices, where its tx and ty
1780
 * components are used to "nudging" fonts around and are handled in gstate
1781
 * and then ignored by the "scaled-font" layer.
1782
 *
1783
 * In order to perform any action on a font, we must build an object
1784
 * called a #cairo_font_scale_t; this contains the central 2x2 matrix
1785
 * resulting from "font matrix * CTM" (sans the font matrix translation
1786
 * components as stated in the previous paragraph).
1787
 *
1788
 * We pass this to the font when making requests of it, which causes it to
1789
 * reply for a particular [user request, device] combination, under the CTM
1790
 * (to accommodate the "zoom in" == "bigger fonts" issue above).
1791
 *
1792
 * The other terms in our communication with the font are therefore in
1793
 * device space. When we ask it to perform text->glyph conversion, it will
1794
 * produce a glyph string in device space. Glyph vectors we pass to it for
1795
 * measuring or rendering should be in device space. The metrics which we
1796
 * get back from the font will be in device space. The contents of the
1797
 * global glyph image cache will be in device space.
1798
 *
1799
 *
1800
 * Cairo's public view
1801
 * -------------------
1802
 *
1803
 * Since the values entering and leaving via public API calls are in user
1804
 * space, the gstate functions typically need to multiply arguments by the
1805
 * CTM (for user-input glyph vectors), and return values by the CTM inverse
1806
 * (for font responses such as metrics or glyph vectors).
1807
 *
1808
 */
1809
 
1810
static cairo_status_t
1811
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
1812
{
1813
    cairo_font_face_t *font_face;
1814
 
1815
    if (gstate->font_face != NULL)
1816
	return gstate->font_face->status;
1817
 
1818
 
1819
    font_face = cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
1820
					    CAIRO_FONT_SLANT_DEFAULT,
1821
					    CAIRO_FONT_WEIGHT_DEFAULT);
1822
    if (font_face->status)
1823
	return font_face->status;
1824
 
1825
    gstate->font_face = font_face;
1826
 
1827
    return CAIRO_STATUS_SUCCESS;
1828
}
1829
 
1830
static cairo_status_t
1831
_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
1832
{
1833
    cairo_status_t status;
1834
    cairo_font_options_t options;
1835
    cairo_scaled_font_t *scaled_font;
1836
 
1837
    if (gstate->scaled_font != NULL)
1838
	return gstate->scaled_font->status;
1839
 
1840
    status = _cairo_gstate_ensure_font_face (gstate);
1841
    if (unlikely (status))
1842
	return status;
1843
 
1844
    cairo_surface_get_font_options (gstate->target, &options);
1845
    cairo_font_options_merge (&options, &gstate->font_options);
1846
 
1847
    scaled_font = cairo_scaled_font_create (gstate->font_face,
1848
				            &gstate->font_matrix,
1849
					    &gstate->ctm,
1850
					    &options);
1851
 
1852
    status = cairo_scaled_font_status (scaled_font);
1853
    if (unlikely (status))
1854
	return status;
1855
 
1856
    gstate->scaled_font = scaled_font;
1857
 
1858
    return CAIRO_STATUS_SUCCESS;
1859
}
1860
 
1861
cairo_status_t
1862
_cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
1863
				cairo_font_extents_t *extents)
1864
{
1865
    cairo_status_t status = _cairo_gstate_ensure_scaled_font (gstate);
1866
    if (unlikely (status))
1867
	return status;
1868
 
1869
    cairo_scaled_font_extents (gstate->scaled_font, extents);
1870
 
1871
    return cairo_scaled_font_status (gstate->scaled_font);
1872
}
1873
 
1874
cairo_status_t
1875
_cairo_gstate_set_font_face (cairo_gstate_t    *gstate,
1876
			     cairo_font_face_t *font_face)
1877
{
1878
    if (font_face && font_face->status)
1879
	return _cairo_error (font_face->status);
1880
 
1881
    if (font_face == gstate->font_face)
1882
	return CAIRO_STATUS_SUCCESS;
1883
 
1884
    cairo_font_face_destroy (gstate->font_face);
1885
    gstate->font_face = cairo_font_face_reference (font_face);
1886
 
1887
    _cairo_gstate_unset_scaled_font (gstate);
1888
 
1889
    return CAIRO_STATUS_SUCCESS;
1890
}
1891
 
1892
cairo_status_t
1893
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
1894
			     const cairo_glyph_t *glyphs,
1895
			     int num_glyphs,
1896
			     cairo_text_extents_t *extents)
1897
{
1898
    cairo_status_t status;
1899
 
1900
    status = _cairo_gstate_ensure_scaled_font (gstate);
1901
    if (unlikely (status))
1902
	return status;
1903
 
1904
    cairo_scaled_font_glyph_extents (gstate->scaled_font,
1905
				     glyphs, num_glyphs,
1906
				     extents);
1907
 
1908
    return cairo_scaled_font_status (gstate->scaled_font);
1909
}
1910
 
1911
cairo_status_t
1912
_cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
1913
				const cairo_glyph_t	   *glyphs,
1914
				int			    num_glyphs,
3959 Serge 1915
				cairo_glyph_text_info_t    *info)
1892 serge 1916
{
3959 Serge 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)];
1892 serge 1919
    cairo_pattern_union_t source_pattern;
3959 Serge 1920
    cairo_glyph_t *transformed_glyphs;
1892 serge 1921
    const cairo_pattern_t *pattern;
1922
    cairo_text_cluster_t *transformed_clusters;
1923
    cairo_operator_t op;
1924
    cairo_status_t status;
1925
 
3959 Serge 1926
    status = _cairo_gstate_get_pattern_status (gstate->source);
1927
    if (unlikely (status))
1928
	return status;
1892 serge 1929
 
1930
    if (gstate->op == CAIRO_OPERATOR_DEST)
1931
	return CAIRO_STATUS_SUCCESS;
1932
 
3959 Serge 1933
    if (_cairo_clip_is_all_clipped (gstate->clip))
1892 serge 1934
	return CAIRO_STATUS_SUCCESS;
1935
 
1936
    status = _cairo_gstate_ensure_scaled_font (gstate);
1937
    if (unlikely (status))
1938
	return status;
1939
 
1940
    transformed_glyphs = stack_transformed_glyphs;
1941
    transformed_clusters = stack_transformed_clusters;
1942
 
1943
    if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) {
1944
	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
3959 Serge 1945
	if (unlikely (transformed_glyphs == NULL))
1946
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1892 serge 1947
    }
1948
 
3959 Serge 1949
    if (info != NULL) {
1950
	if (info->num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) {
1951
	    transformed_clusters = cairo_text_cluster_allocate (info->num_clusters);
1952
	    if (unlikely (transformed_clusters == NULL)) {
1953
		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1954
		goto CLEANUP_GLYPHS;
1955
	    }
1956
	}
1892 serge 1957
 
3959 Serge 1958
	_cairo_gstate_transform_glyphs_to_backend (gstate,
1959
						   glyphs, num_glyphs,
1960
						   info->clusters,
1961
						   info->num_clusters,
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,
1971
						   &num_glyphs,
1972
						   NULL);
1892 serge 1973
    }
1974
 
3959 Serge 1975
    if (num_glyphs == 0)
1892 serge 1976
	goto CLEANUP_GLYPHS;
1977
 
1978
    op = _reduce_op (gstate);
1979
    if (op == CAIRO_OPERATOR_CLEAR) {
1980
	pattern = &_cairo_pattern_clear.base;
1981
    } else {
1982
	_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
1983
	pattern = &source_pattern.base;
1984
    }
1985
 
1986
    /* For really huge font sizes, we can just do path;fill instead of
1987
     * show_glyphs, as show_glyphs would put excess pressure on the cache,
1988
     * and moreover, not all components below us correctly handle huge font
1989
     * sizes.  I wanted to set the limit at 256.  But alas, seems like cairo's
1990
     * rasterizer is something like ten times slower than freetype's for huge
1991
     * sizes.  So, no win just yet.  For now, do it for insanely-huge sizes,
1992
     * just to make sure we don't make anyone unhappy.  When we get a really
1993
     * fast rasterizer in cairo, we may want to readjust this.
1994
     *
1995
     * Needless to say, do this only if show_text_glyphs is not available. */
1996
    if (cairo_surface_has_show_text_glyphs (gstate->target) ||
1997
	_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240)
1998
    {
3959 Serge 1999
	if (info != NULL) {
2000
	    status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
2001
						      info->utf8, info->utf8_len,
2002
						      transformed_glyphs, num_glyphs,
2003
						      transformed_clusters, info->num_clusters,
2004
						      info->cluster_flags,
2005
						      gstate->scaled_font,
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
	}
1892 serge 2015
    }
2016
    else
2017
    {
2018
	cairo_path_fixed_t path;
2019
 
2020
	_cairo_path_fixed_init (&path);
2021
 
2022
	status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
2023
						transformed_glyphs, num_glyphs,
2024
						&path);
2025
 
2026
	if (status == CAIRO_STATUS_SUCCESS) {
2027
	    status = _cairo_surface_fill (gstate->target, op, pattern,
2028
					  &path,
2029
					  CAIRO_FILL_RULE_WINDING,
2030
					  gstate->tolerance,
2031
					  gstate->scaled_font->options.antialias,
3959 Serge 2032
					  gstate->clip);
1892 serge 2033
	}
2034
 
2035
	_cairo_path_fixed_fini (&path);
2036
    }
2037
 
2038
CLEANUP_GLYPHS:
2039
    if (transformed_glyphs != stack_transformed_glyphs)
2040
      cairo_glyph_free (transformed_glyphs);
2041
    if (transformed_clusters != stack_transformed_clusters)
2042
      cairo_text_cluster_free (transformed_clusters);
2043
 
2044
    return status;
2045
}
2046
 
2047
cairo_status_t
2048
_cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
2049
			  const cairo_glyph_t *glyphs,
2050
			  int		       num_glyphs,
2051
			  cairo_path_fixed_t  *path)
2052
{
3959 Serge 2053
    cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
2054
    cairo_glyph_t *transformed_glyphs;
1892 serge 2055
    cairo_status_t status;
2056
 
2057
    status = _cairo_gstate_ensure_scaled_font (gstate);
2058
    if (unlikely (status))
2059
	return status;
2060
 
2061
    if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs)) {
3959 Serge 2062
	transformed_glyphs = stack_transformed_glyphs;
1892 serge 2063
    } else {
2064
	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
2065
	if (unlikely (transformed_glyphs == NULL))
2066
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2067
    }
2068
 
3959 Serge 2069
    _cairo_gstate_transform_glyphs_to_backend (gstate,
2070
					       glyphs, num_glyphs,
2071
					       NULL, 0, 0,
2072
					       transformed_glyphs,
2073
					       &num_glyphs, NULL);
1892 serge 2074
 
2075
    status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
2076
					    transformed_glyphs, num_glyphs,
2077
					    path);
2078
 
2079
    if (transformed_glyphs != stack_transformed_glyphs)
2080
      cairo_glyph_free (transformed_glyphs);
2081
 
2082
    return status;
2083
}
2084
 
2085
cairo_status_t
2086
_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
2087
			     cairo_antialias_t antialias)
2088
{
2089
    gstate->antialias = antialias;
2090
 
2091
    return CAIRO_STATUS_SUCCESS;
2092
}
2093
 
2094
cairo_antialias_t
2095
_cairo_gstate_get_antialias (cairo_gstate_t *gstate)
2096
{
2097
    return gstate->antialias;
2098
}
2099
 
2100
/**
2101
 * _cairo_gstate_transform_glyphs_to_backend:
2102
 * @gstate: a #cairo_gstate_t
2103
 * @glyphs: the array of #cairo_glyph_t objects to be transformed
2104
 * @num_glyphs: the number of elements in @glyphs
2105
 * @transformed_glyphs: a pre-allocated array of at least @num_glyphs
2106
 * #cairo_glyph_t objects
2107
 * @num_transformed_glyphs: the number of elements in @transformed_glyphs
2108
 * after dropping out of bounds glyphs, or %NULL if glyphs shouldn't be
2109
 * dropped
2110
 *
2111
 * Transform an array of glyphs to backend space by first adding the offset
2112
 * of the font matrix, then transforming from user space to backend space.
2113
 * The result of the transformation is placed in @transformed_glyphs.
2114
 *
2115
 * This also uses information from the scaled font and the surface to
2116
 * cull/drop glyphs that will not be visible.
2117
 **/
3959 Serge 2118
static void
1892 serge 2119
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t	*gstate,
2120
                                           const cairo_glyph_t	*glyphs,
2121
                                           int			 num_glyphs,
2122
					   const cairo_text_cluster_t	*clusters,
2123
					   int			 num_clusters,
2124
					   cairo_text_cluster_flags_t cluster_flags,
2125
                                           cairo_glyph_t	*transformed_glyphs,
2126
					   int			*num_transformed_glyphs,
2127
					   cairo_text_cluster_t *transformed_clusters)
2128
{
3959 Serge 2129
    cairo_rectangle_int_t surface_extents;
1892 serge 2130
    cairo_matrix_t *ctm = &gstate->ctm;
2131
    cairo_matrix_t *font_matrix = &gstate->font_matrix;
2132
    cairo_matrix_t *device_transform = &gstate->target->device_transform;
2133
    cairo_bool_t drop = FALSE;
2134
    double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
3959 Serge 2135
    int i, j, k;
1892 serge 2136
 
3959 Serge 2137
    drop = TRUE;
2138
    if (! _cairo_gstate_int_clip_extents (gstate, &surface_extents)) {
2139
	drop = FALSE; /* unbounded surface */
2140
    } else {
2141
	double scale10 = 10 * _cairo_scaled_font_get_max_scale (gstate->scaled_font);
2142
	if (surface_extents.width == 0 || surface_extents.height == 0) {
2143
	  /* No visible area.  Don't draw anything */
2144
	  *num_transformed_glyphs = 0;
2145
	  return;
1892 serge 2146
	}
3959 Serge 2147
	/* XXX We currently drop any glyphs that has its position outside
2148
	 * of the surface boundaries by a safety margin depending on the
2149
	 * font scale.  This however can fail in extreme cases where the
2150
	 * font has really long swashes for example...  We can correctly
2151
	 * handle that by looking the glyph up and using its device bbox
2152
	 * to device if it's going to be visible, but I'm not inclined to
2153
	 * do that now.
2154
	 */
2155
	x1 = surface_extents.x - scale10;
2156
	y1 = surface_extents.y - scale10;
2157
	x2 = surface_extents.x + (int) surface_extents.width  + scale10;
2158
	y2 = surface_extents.y + (int) surface_extents.height + scale10;
2159
    }
1892 serge 2160
 
3959 Serge 2161
    if (!drop)
2162
	*num_transformed_glyphs = num_glyphs;
1892 serge 2163
 
2164
#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
2165
 
2166
    j = 0;
2167
    if (_cairo_matrix_is_identity (ctm) &&
2168
        _cairo_matrix_is_identity (device_transform) &&
2169
	font_matrix->x0 == 0 && font_matrix->y0 == 0)
2170
    {
2171
	if (! drop) {
2172
	    memcpy (transformed_glyphs, glyphs,
2173
		    num_glyphs * sizeof (cairo_glyph_t));
3959 Serge 2174
	    memcpy (transformed_clusters, clusters,
2175
		    num_clusters * sizeof (cairo_text_cluster_t));
1892 serge 2176
	    j = num_glyphs;
2177
	} else if (num_clusters == 0) {
2178
	    for (i = 0; i < num_glyphs; i++) {
2179
		transformed_glyphs[j].index = glyphs[i].index;
2180
		transformed_glyphs[j].x = glyphs[i].x;
2181
		transformed_glyphs[j].y = glyphs[i].y;
2182
		if (KEEP_GLYPH (transformed_glyphs[j]))
2183
		    j++;
2184
	    }
2185
	} else {
2186
	    const cairo_glyph_t *cur_glyph;
2187
 
2188
	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
2189
		cur_glyph = glyphs + num_glyphs - 1;
2190
	    else
2191
		cur_glyph = glyphs;
2192
 
2193
	    for (i = 0; i < num_clusters; i++) {
2194
		cairo_bool_t cluster_visible = FALSE;
2195
 
2196
		for (k = 0; k < clusters[i].num_glyphs; k++) {
2197
		    transformed_glyphs[j+k].index = cur_glyph->index;
2198
		    transformed_glyphs[j+k].x = cur_glyph->x;
2199
		    transformed_glyphs[j+k].y = cur_glyph->y;
2200
		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
2201
			cluster_visible = TRUE;
2202
 
2203
		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
2204
			cur_glyph--;
2205
		    else
2206
			cur_glyph++;
2207
		}
2208
 
2209
		transformed_clusters[i] = clusters[i];
2210
		if (cluster_visible)
2211
		    j += k;
2212
		else
2213
		    transformed_clusters[i].num_glyphs = 0;
2214
	    }
2215
	}
2216
    }
2217
    else if (_cairo_matrix_is_translation (ctm) &&
2218
             _cairo_matrix_is_translation (device_transform))
2219
    {
2220
        double tx = font_matrix->x0 + ctm->x0 + device_transform->x0;
2221
        double ty = font_matrix->y0 + ctm->y0 + device_transform->y0;
2222
 
2223
	if (! drop || num_clusters == 0) {
2224
	    for (i = 0; i < num_glyphs; i++) {
2225
		transformed_glyphs[j].index = glyphs[i].index;
2226
		transformed_glyphs[j].x = glyphs[i].x + tx;
2227
		transformed_glyphs[j].y = glyphs[i].y + ty;
2228
		if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
2229
		    j++;
2230
	    }
3959 Serge 2231
	    memcpy (transformed_clusters, clusters,
2232
		    num_clusters * sizeof (cairo_text_cluster_t));
1892 serge 2233
	} else {
2234
	    const cairo_glyph_t *cur_glyph;
2235
 
2236
	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
2237
		cur_glyph = glyphs + num_glyphs - 1;
2238
	    else
2239
		cur_glyph = glyphs;
2240
 
2241
	    for (i = 0; i < num_clusters; i++) {
2242
		cairo_bool_t cluster_visible = FALSE;
2243
 
2244
		for (k = 0; k < clusters[i].num_glyphs; k++) {
2245
		    transformed_glyphs[j+k].index = cur_glyph->index;
2246
		    transformed_glyphs[j+k].x = cur_glyph->x + tx;
2247
		    transformed_glyphs[j+k].y = cur_glyph->y + ty;
2248
		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
2249
			cluster_visible = TRUE;
2250
 
2251
		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
2252
			cur_glyph--;
2253
		    else
2254
			cur_glyph++;
2255
		}
2256
 
2257
		transformed_clusters[i] = clusters[i];
2258
		if (cluster_visible)
2259
		    j += k;
2260
		else
2261
		    transformed_clusters[i].num_glyphs = 0;
2262
	    }
2263
	}
2264
    }
2265
    else
2266
    {
2267
        cairo_matrix_t aggregate_transform;
2268
 
2269
        cairo_matrix_init_translate (&aggregate_transform,
2270
                                     gstate->font_matrix.x0,
2271
                                     gstate->font_matrix.y0);
2272
        cairo_matrix_multiply (&aggregate_transform,
2273
                               &aggregate_transform, ctm);
2274
        cairo_matrix_multiply (&aggregate_transform,
2275
                               &aggregate_transform, device_transform);
2276
 
2277
	if (! drop || num_clusters == 0) {
2278
	    for (i = 0; i < num_glyphs; i++) {
2279
		transformed_glyphs[j] = glyphs[i];
2280
		cairo_matrix_transform_point (&aggregate_transform,
2281
					      &transformed_glyphs[j].x,
2282
					      &transformed_glyphs[j].y);
2283
		if (! drop || KEEP_GLYPH (transformed_glyphs[j]))
2284
		    j++;
2285
	    }
3959 Serge 2286
	    memcpy (transformed_clusters, clusters,
2287
		    num_clusters * sizeof (cairo_text_cluster_t));
1892 serge 2288
	} else {
2289
	    const cairo_glyph_t *cur_glyph;
2290
 
2291
	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
2292
		cur_glyph = glyphs + num_glyphs - 1;
2293
	    else
2294
		cur_glyph = glyphs;
2295
 
2296
	    for (i = 0; i < num_clusters; i++) {
2297
		cairo_bool_t cluster_visible = FALSE;
2298
		for (k = 0; k < clusters[i].num_glyphs; k++) {
2299
		    transformed_glyphs[j+k] = *cur_glyph;
2300
		    cairo_matrix_transform_point (&aggregate_transform,
2301
						  &transformed_glyphs[j+k].x,
2302
						  &transformed_glyphs[j+k].y);
2303
		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
2304
			cluster_visible = TRUE;
2305
 
2306
		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
2307
			cur_glyph--;
2308
		    else
2309
			cur_glyph++;
2310
		}
2311
 
2312
		transformed_clusters[i] = clusters[i];
2313
		if (cluster_visible)
2314
		    j += k;
2315
		else
2316
		    transformed_clusters[i].num_glyphs = 0;
2317
	    }
2318
	}
2319
    }
2320
    *num_transformed_glyphs = j;
2321
 
2322
    if (num_clusters != 0 && cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) {
2323
	for (i = 0; i < --j; i++) {
2324
	    cairo_glyph_t tmp;
2325
 
2326
	    tmp = transformed_glyphs[i];
2327
	    transformed_glyphs[i] = transformed_glyphs[j];
2328
	    transformed_glyphs[j] = tmp;
2329
	}
2330
    }
2331
}