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