1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2002 University of Southern California
5 * Copyright © 2005 Red Hat, Inc.
6 * Copyright © 2011 Intel Corporation
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is University of Southern
37 * Carl D. Worth <cworth@cworth.org>
38 * Chris Wilson <chris@chris-wilson.co.uk>
43 #include "cairo-private.h"
44 #include "cairo-arc-private.h"
45 #include "cairo-backend-private.h"
46 #include "cairo-clip-inline.h"
47 #include "cairo-default-context-private.h"
48 #include "cairo-error-private.h"
49 #include "cairo-freed-pool-private.h"
50 #include "cairo-path-private.h"
51 #include "cairo-pattern-private.h"
53 #define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1)
55 #if !defined(INFINITY)
56 #define INFINITY HUGE_VAL
59 static freed_pool_t context_pool;
62 _cairo_default_context_reset_static_data (void)
64 _freed_pool_reset (&context_pool);
68 _cairo_default_context_fini (cairo_default_context_t *cr)
70 while (cr->gstate != &cr->gstate_tail[0]) {
71 if (_cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist))
75 _cairo_gstate_fini (cr->gstate);
76 cr->gstate_freelist = cr->gstate_freelist->next; /* skip over tail[1] */
77 while (cr->gstate_freelist != NULL) {
78 cairo_gstate_t *gstate = cr->gstate_freelist;
79 cr->gstate_freelist = gstate->next;
83 _cairo_path_fixed_fini (cr->path);
85 _cairo_fini (&cr->base);
89 _cairo_default_context_destroy (void *abstract_cr)
91 cairo_default_context_t *cr = abstract_cr;
93 _cairo_default_context_fini (cr);
95 /* mark the context as invalid to protect against misuse */
96 cr->base.status = CAIRO_STATUS_NULL_POINTER;
97 _freed_pool_put (&context_pool, cr);
100 static cairo_surface_t *
101 _cairo_default_context_get_original_target (void *abstract_cr)
103 cairo_default_context_t *cr = abstract_cr;
105 return _cairo_gstate_get_original_target (cr->gstate);
108 static cairo_surface_t *
109 _cairo_default_context_get_current_target (void *abstract_cr)
111 cairo_default_context_t *cr = abstract_cr;
113 return _cairo_gstate_get_target (cr->gstate);
116 static cairo_status_t
117 _cairo_default_context_save (void *abstract_cr)
119 cairo_default_context_t *cr = abstract_cr;
121 return _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
124 static cairo_status_t
125 _cairo_default_context_restore (void *abstract_cr)
127 cairo_default_context_t *cr = abstract_cr;
129 if (unlikely (_cairo_gstate_is_group (cr->gstate)))
130 return _cairo_error (CAIRO_STATUS_INVALID_RESTORE);
132 return _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
135 static cairo_status_t
136 _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
138 cairo_default_context_t *cr = abstract_cr;
139 cairo_surface_t *group_surface;
141 cairo_status_t status;
143 clip = _cairo_gstate_get_clip (cr->gstate);
144 if (_cairo_clip_is_all_clipped (clip)) {
145 group_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
146 status = group_surface->status;
147 if (unlikely (status))
150 cairo_surface_t *parent_surface;
151 cairo_rectangle_int_t extents;
152 cairo_bool_t is_empty;
154 parent_surface = _cairo_gstate_get_target (cr->gstate);
156 /* Get the extents that we'll use in creating our new group surface */
157 is_empty = _cairo_surface_get_extents (parent_surface, &extents);
159 is_empty = _cairo_rectangle_intersect (&extents,
160 _cairo_clip_get_extents (clip));
162 /* XXX unbounded surface creation */
164 group_surface = _cairo_surface_create_similar_solid (parent_surface,
168 CAIRO_COLOR_TRANSPARENT);
169 status = group_surface->status;
170 if (unlikely (status))
173 /* Set device offsets on the new surface so that logically it appears at
174 * the same location on the parent surface -- when we pop_group this,
175 * the source pattern will get fixed up for the appropriate target surface
176 * device offsets, so we want to set our own surface offsets from /that/,
177 * and not from the device origin. */
178 cairo_surface_set_device_offset (group_surface,
179 parent_surface->device_transform.x0 - extents.x,
180 parent_surface->device_transform.y0 - extents.y);
182 /* If we have a current path, we need to adjust it to compensate for
183 * the device offset just applied. */
184 _cairo_path_fixed_translate (cr->path,
185 _cairo_fixed_from_int (-extents.x),
186 _cairo_fixed_from_int (-extents.y));
189 /* create a new gstate for the redirect */
190 status = _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
191 if (unlikely (status))
194 status = _cairo_gstate_redirect_target (cr->gstate, group_surface);
197 cairo_surface_destroy (group_surface);
201 static cairo_pattern_t *
202 _cairo_default_context_pop_group (void *abstract_cr)
204 cairo_default_context_t *cr = abstract_cr;
205 cairo_surface_t *group_surface;
206 cairo_pattern_t *group_pattern;
207 cairo_matrix_t group_matrix, device_transform_matrix;
208 cairo_status_t status;
210 /* Verify that we are at the right nesting level */
211 if (unlikely (! _cairo_gstate_is_group (cr->gstate)))
212 return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_POP_GROUP);
214 /* Get a reference to the active surface before restoring */
215 group_surface = _cairo_gstate_get_target (cr->gstate);
216 group_surface = cairo_surface_reference (group_surface);
218 status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
219 assert (status == CAIRO_STATUS_SUCCESS);
221 group_pattern = cairo_pattern_create_for_surface (group_surface);
222 status = group_pattern->status;
223 if (unlikely (status))
226 _cairo_gstate_get_matrix (cr->gstate, &group_matrix);
227 /* Transform by group_matrix centered around device_transform so that when
228 * we call _cairo_gstate_copy_transformed_pattern the result is a pattern
229 * with a matrix equivalent to the device_transform of group_surface. */
230 if (_cairo_surface_has_device_transform (group_surface)) {
231 cairo_pattern_set_matrix (group_pattern, &group_surface->device_transform);
232 _cairo_pattern_transform (group_pattern, &group_matrix);
233 _cairo_pattern_transform (group_pattern, &group_surface->device_transform_inverse);
235 cairo_pattern_set_matrix (group_pattern, &group_matrix);
238 /* If we have a current path, we need to adjust it to compensate for
239 * the device offset just removed. */
240 cairo_matrix_multiply (&device_transform_matrix,
241 &_cairo_gstate_get_target (cr->gstate)->device_transform,
242 &group_surface->device_transform_inverse);
243 _cairo_path_fixed_transform (cr->path, &device_transform_matrix);
246 cairo_surface_destroy (group_surface);
248 return group_pattern;
251 static cairo_status_t
252 _cairo_default_context_set_source (void *abstract_cr,
253 cairo_pattern_t *source)
255 cairo_default_context_t *cr = abstract_cr;
257 return _cairo_gstate_set_source (cr->gstate, source);
261 _current_source_matches_solid (const cairo_pattern_t *pattern,
269 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
272 red = _cairo_restrict_value (red, 0.0, 1.0);
273 green = _cairo_restrict_value (green, 0.0, 1.0);
274 blue = _cairo_restrict_value (blue, 0.0, 1.0);
275 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
277 _cairo_color_init_rgba (&color, red, green, blue, alpha);
278 return _cairo_color_equal (&color,
279 &((cairo_solid_pattern_t *) pattern)->color);
282 static cairo_status_t
283 _cairo_default_context_set_source_rgba (void *abstract_cr, double red, double green, double blue, double alpha)
285 cairo_default_context_t *cr = abstract_cr;
286 cairo_pattern_t *pattern;
287 cairo_status_t status;
289 if (_current_source_matches_solid (cr->gstate->source,
290 red, green, blue, alpha))
291 return CAIRO_STATUS_SUCCESS;
293 /* push the current pattern to the freed lists */
294 _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
296 pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
297 if (unlikely (pattern->status))
298 return pattern->status;
300 status = _cairo_default_context_set_source (cr, pattern);
301 cairo_pattern_destroy (pattern);
306 static cairo_status_t
307 _cairo_default_context_set_source_surface (void *abstract_cr,
308 cairo_surface_t *surface,
312 cairo_default_context_t *cr = abstract_cr;
313 cairo_pattern_t *pattern;
314 cairo_matrix_t matrix;
315 cairo_status_t status;
317 /* push the current pattern to the freed lists */
318 _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
320 pattern = cairo_pattern_create_for_surface (surface);
321 if (unlikely (pattern->status))
322 return pattern->status;
324 cairo_matrix_init_translate (&matrix, -x, -y);
325 cairo_pattern_set_matrix (pattern, &matrix);
327 status = _cairo_default_context_set_source (cr, pattern);
328 cairo_pattern_destroy (pattern);
333 static cairo_pattern_t *
334 _cairo_default_context_get_source (void *abstract_cr)
336 cairo_default_context_t *cr = abstract_cr;
338 return _cairo_gstate_get_source (cr->gstate);
341 static cairo_status_t
342 _cairo_default_context_set_tolerance (void *abstract_cr,
345 cairo_default_context_t *cr = abstract_cr;
347 if (tolerance < CAIRO_TOLERANCE_MINIMUM)
348 tolerance = CAIRO_TOLERANCE_MINIMUM;
350 return _cairo_gstate_set_tolerance (cr->gstate, tolerance);
353 static cairo_status_t
354 _cairo_default_context_set_operator (void *abstract_cr, cairo_operator_t op)
356 cairo_default_context_t *cr = abstract_cr;
358 return _cairo_gstate_set_operator (cr->gstate, op);
361 static cairo_status_t
362 _cairo_default_context_set_opacity (void *abstract_cr, double opacity)
364 cairo_default_context_t *cr = abstract_cr;
366 return _cairo_gstate_set_opacity (cr->gstate, opacity);
369 static cairo_status_t
370 _cairo_default_context_set_antialias (void *abstract_cr,
371 cairo_antialias_t antialias)
373 cairo_default_context_t *cr = abstract_cr;
375 return _cairo_gstate_set_antialias (cr->gstate, antialias);
378 static cairo_status_t
379 _cairo_default_context_set_fill_rule (void *abstract_cr,
380 cairo_fill_rule_t fill_rule)
382 cairo_default_context_t *cr = abstract_cr;
384 return _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
387 static cairo_status_t
388 _cairo_default_context_set_line_width (void *abstract_cr,
391 cairo_default_context_t *cr = abstract_cr;
393 return _cairo_gstate_set_line_width (cr->gstate, line_width);
396 static cairo_status_t
397 _cairo_default_context_set_line_cap (void *abstract_cr,
398 cairo_line_cap_t line_cap)
400 cairo_default_context_t *cr = abstract_cr;
402 return _cairo_gstate_set_line_cap (cr->gstate, line_cap);
405 static cairo_status_t
406 _cairo_default_context_set_line_join (void *abstract_cr,
407 cairo_line_join_t line_join)
409 cairo_default_context_t *cr = abstract_cr;
411 return _cairo_gstate_set_line_join (cr->gstate, line_join);
414 static cairo_status_t
415 _cairo_default_context_set_dash (void *abstract_cr,
416 const double *dashes,
420 cairo_default_context_t *cr = abstract_cr;
422 return _cairo_gstate_set_dash (cr->gstate,
423 dashes, num_dashes, offset);
426 static cairo_status_t
427 _cairo_default_context_set_miter_limit (void *abstract_cr,
430 cairo_default_context_t *cr = abstract_cr;
432 return _cairo_gstate_set_miter_limit (cr->gstate, limit);
435 static cairo_antialias_t
436 _cairo_default_context_get_antialias (void *abstract_cr)
438 cairo_default_context_t *cr = abstract_cr;
440 return _cairo_gstate_get_antialias (cr->gstate);
444 _cairo_default_context_get_dash (void *abstract_cr,
449 cairo_default_context_t *cr = abstract_cr;
451 _cairo_gstate_get_dash (cr->gstate, dashes, num_dashes, offset);
454 static cairo_fill_rule_t
455 _cairo_default_context_get_fill_rule (void *abstract_cr)
457 cairo_default_context_t *cr = abstract_cr;
459 return _cairo_gstate_get_fill_rule (cr->gstate);
463 _cairo_default_context_get_line_width (void *abstract_cr)
465 cairo_default_context_t *cr = abstract_cr;
467 return _cairo_gstate_get_line_width (cr->gstate);
470 static cairo_line_cap_t
471 _cairo_default_context_get_line_cap (void *abstract_cr)
473 cairo_default_context_t *cr = abstract_cr;
475 return _cairo_gstate_get_line_cap (cr->gstate);
478 static cairo_line_join_t
479 _cairo_default_context_get_line_join (void *abstract_cr)
481 cairo_default_context_t *cr = abstract_cr;
483 return _cairo_gstate_get_line_join (cr->gstate);
487 _cairo_default_context_get_miter_limit (void *abstract_cr)
489 cairo_default_context_t *cr = abstract_cr;
491 return _cairo_gstate_get_miter_limit (cr->gstate);
494 static cairo_operator_t
495 _cairo_default_context_get_operator (void *abstract_cr)
497 cairo_default_context_t *cr = abstract_cr;
499 return _cairo_gstate_get_operator (cr->gstate);
503 _cairo_default_context_get_opacity (void *abstract_cr)
505 cairo_default_context_t *cr = abstract_cr;
507 return _cairo_gstate_get_opacity (cr->gstate);
511 _cairo_default_context_get_tolerance (void *abstract_cr)
513 cairo_default_context_t *cr = abstract_cr;
515 return _cairo_gstate_get_tolerance (cr->gstate);
519 /* Current tranformation matrix */
521 static cairo_status_t
522 _cairo_default_context_translate (void *abstract_cr,
526 cairo_default_context_t *cr = abstract_cr;
528 return _cairo_gstate_translate (cr->gstate, tx, ty);
531 static cairo_status_t
532 _cairo_default_context_scale (void *abstract_cr,
536 cairo_default_context_t *cr = abstract_cr;
538 return _cairo_gstate_scale (cr->gstate, sx, sy);
541 static cairo_status_t
542 _cairo_default_context_rotate (void *abstract_cr,
545 cairo_default_context_t *cr = abstract_cr;
547 return _cairo_gstate_rotate (cr->gstate, theta);
550 static cairo_status_t
551 _cairo_default_context_transform (void *abstract_cr,
552 const cairo_matrix_t *matrix)
554 cairo_default_context_t *cr = abstract_cr;
556 return _cairo_gstate_transform (cr->gstate, matrix);
559 static cairo_status_t
560 _cairo_default_context_set_matrix (void *abstract_cr,
561 const cairo_matrix_t *matrix)
563 cairo_default_context_t *cr = abstract_cr;
565 return _cairo_gstate_set_matrix (cr->gstate, matrix);
568 static cairo_status_t
569 _cairo_default_context_set_identity_matrix (void *abstract_cr)
571 cairo_default_context_t *cr = abstract_cr;
573 _cairo_gstate_identity_matrix (cr->gstate);
574 return CAIRO_STATUS_SUCCESS;
578 _cairo_default_context_get_matrix (void *abstract_cr,
579 cairo_matrix_t *matrix)
581 cairo_default_context_t *cr = abstract_cr;
583 _cairo_gstate_get_matrix (cr->gstate, matrix);
587 _cairo_default_context_user_to_device (void *abstract_cr,
591 cairo_default_context_t *cr = abstract_cr;
593 _cairo_gstate_user_to_device (cr->gstate, x, y);
597 _cairo_default_context_user_to_device_distance (void *abstract_cr, double *dx, double *dy)
599 cairo_default_context_t *cr = abstract_cr;
601 _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy);
605 _cairo_default_context_device_to_user (void *abstract_cr,
609 cairo_default_context_t *cr = abstract_cr;
611 _cairo_gstate_device_to_user (cr->gstate, x, y);
615 _cairo_default_context_device_to_user_distance (void *abstract_cr,
619 cairo_default_context_t *cr = abstract_cr;
621 _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy);
624 /* Path constructor */
626 static cairo_status_t
627 _cairo_default_context_new_path (void *abstract_cr)
629 cairo_default_context_t *cr = abstract_cr;
631 _cairo_path_fixed_fini (cr->path);
632 _cairo_path_fixed_init (cr->path);
634 return CAIRO_STATUS_SUCCESS;
637 static cairo_status_t
638 _cairo_default_context_new_sub_path (void *abstract_cr)
640 cairo_default_context_t *cr = abstract_cr;
642 _cairo_path_fixed_new_sub_path (cr->path);
644 return CAIRO_STATUS_SUCCESS;
647 static cairo_status_t
648 _cairo_default_context_move_to (void *abstract_cr, double x, double y)
650 cairo_default_context_t *cr = abstract_cr;
651 cairo_fixed_t x_fixed, y_fixed;
653 _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
654 x_fixed = _cairo_fixed_from_double (x);
655 y_fixed = _cairo_fixed_from_double (y);
657 return _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed);
660 static cairo_status_t
661 _cairo_default_context_line_to (void *abstract_cr, double x, double y)
663 cairo_default_context_t *cr = abstract_cr;
664 cairo_fixed_t x_fixed, y_fixed;
666 _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
667 x_fixed = _cairo_fixed_from_double (x);
668 y_fixed = _cairo_fixed_from_double (y);
670 return _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
673 static cairo_status_t
674 _cairo_default_context_curve_to (void *abstract_cr,
675 double x1, double y1,
676 double x2, double y2,
677 double x3, double y3)
679 cairo_default_context_t *cr = abstract_cr;
680 cairo_fixed_t x1_fixed, y1_fixed;
681 cairo_fixed_t x2_fixed, y2_fixed;
682 cairo_fixed_t x3_fixed, y3_fixed;
684 _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
685 _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
686 _cairo_gstate_user_to_backend (cr->gstate, &x3, &y3);
688 x1_fixed = _cairo_fixed_from_double (x1);
689 y1_fixed = _cairo_fixed_from_double (y1);
691 x2_fixed = _cairo_fixed_from_double (x2);
692 y2_fixed = _cairo_fixed_from_double (y2);
694 x3_fixed = _cairo_fixed_from_double (x3);
695 y3_fixed = _cairo_fixed_from_double (y3);
697 return _cairo_path_fixed_curve_to (cr->path,
703 static cairo_status_t
704 _cairo_default_context_arc (void *abstract_cr,
705 double xc, double yc, double radius,
706 double angle1, double angle2,
707 cairo_bool_t forward)
709 cairo_default_context_t *cr = abstract_cr;
710 cairo_status_t status;
712 /* Do nothing, successfully, if radius is <= 0 */
714 cairo_fixed_t x_fixed, y_fixed;
716 _cairo_gstate_user_to_backend (cr->gstate, &xc, &yc);
717 x_fixed = _cairo_fixed_from_double (xc);
718 y_fixed = _cairo_fixed_from_double (yc);
719 status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
720 if (unlikely (status))
723 status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
724 if (unlikely (status))
727 return CAIRO_STATUS_SUCCESS;
730 status = _cairo_default_context_line_to (cr,
731 xc + radius * cos (angle1),
732 yc + radius * sin (angle1));
734 if (unlikely (status))
738 _cairo_arc_path (&cr->base, xc, yc, radius, angle1, angle2);
740 _cairo_arc_path_negative (&cr->base, xc, yc, radius, angle1, angle2);
742 return CAIRO_STATUS_SUCCESS; /* any error will have already been set on cr */
745 static cairo_status_t
746 _cairo_default_context_rel_move_to (void *abstract_cr, double dx, double dy)
748 cairo_default_context_t *cr = abstract_cr;
749 cairo_fixed_t dx_fixed, dy_fixed;
751 _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
753 dx_fixed = _cairo_fixed_from_double (dx);
754 dy_fixed = _cairo_fixed_from_double (dy);
756 return _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed);
759 static cairo_status_t
760 _cairo_default_context_rel_line_to (void *abstract_cr, double dx, double dy)
762 cairo_default_context_t *cr = abstract_cr;
763 cairo_fixed_t dx_fixed, dy_fixed;
765 _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
767 dx_fixed = _cairo_fixed_from_double (dx);
768 dy_fixed = _cairo_fixed_from_double (dy);
770 return _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed);
774 static cairo_status_t
775 _cairo_default_context_rel_curve_to (void *abstract_cr,
776 double dx1, double dy1,
777 double dx2, double dy2,
778 double dx3, double dy3)
780 cairo_default_context_t *cr = abstract_cr;
781 cairo_fixed_t dx1_fixed, dy1_fixed;
782 cairo_fixed_t dx2_fixed, dy2_fixed;
783 cairo_fixed_t dx3_fixed, dy3_fixed;
785 _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1);
786 _cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2);
787 _cairo_gstate_user_to_device_distance (cr->gstate, &dx3, &dy3);
789 dx1_fixed = _cairo_fixed_from_double (dx1);
790 dy1_fixed = _cairo_fixed_from_double (dy1);
792 dx2_fixed = _cairo_fixed_from_double (dx2);
793 dy2_fixed = _cairo_fixed_from_double (dy2);
795 dx3_fixed = _cairo_fixed_from_double (dx3);
796 dy3_fixed = _cairo_fixed_from_double (dy3);
798 return _cairo_path_fixed_rel_curve_to (cr->path,
799 dx1_fixed, dy1_fixed,
800 dx2_fixed, dy2_fixed,
801 dx3_fixed, dy3_fixed);
804 static cairo_status_t
805 _cairo_default_context_close_path (void *abstract_cr)
807 cairo_default_context_t *cr = abstract_cr;
809 return _cairo_path_fixed_close_path (cr->path);
812 static cairo_status_t
813 _cairo_default_context_rectangle (void *abstract_cr,
815 double width, double height)
817 cairo_default_context_t *cr = abstract_cr;
818 cairo_status_t status;
820 status = _cairo_default_context_move_to (cr, x, y);
821 if (unlikely (status))
824 status = _cairo_default_context_rel_line_to (cr, width, 0);
825 if (unlikely (status))
828 status = _cairo_default_context_rel_line_to (cr, 0, height);
829 if (unlikely (status))
832 status = _cairo_default_context_rel_line_to (cr, -width, 0);
833 if (unlikely (status))
836 return _cairo_default_context_close_path (cr);
840 _cairo_default_context_path_extents (void *abstract_cr,
846 cairo_default_context_t *cr = abstract_cr;
848 _cairo_gstate_path_extents (cr->gstate,
854 _cairo_default_context_has_current_point (void *abstract_cr)
856 cairo_default_context_t *cr = abstract_cr;
858 return cr->path->has_current_point;
862 _cairo_default_context_get_current_point (void *abstract_cr,
866 cairo_default_context_t *cr = abstract_cr;
867 cairo_fixed_t x_fixed, y_fixed;
869 if (_cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed))
871 *x = _cairo_fixed_to_double (x_fixed);
872 *y = _cairo_fixed_to_double (y_fixed);
873 _cairo_gstate_backend_to_user (cr->gstate, x, y);
883 static cairo_path_t *
884 _cairo_default_context_copy_path (void *abstract_cr)
886 cairo_default_context_t *cr = abstract_cr;
888 return _cairo_path_create (cr->path, &cr->base);
891 static cairo_path_t *
892 _cairo_default_context_copy_path_flat (void *abstract_cr)
894 cairo_default_context_t *cr = abstract_cr;
896 return _cairo_path_create_flat (cr->path, &cr->base);
899 static cairo_status_t
900 _cairo_default_context_append_path (void *abstract_cr,
901 const cairo_path_t *path)
903 cairo_default_context_t *cr = abstract_cr;
905 return _cairo_path_append_to_context (path, &cr->base);
908 static cairo_status_t
909 _cairo_default_context_paint (void *abstract_cr)
911 cairo_default_context_t *cr = abstract_cr;
913 return _cairo_gstate_paint (cr->gstate);
916 static cairo_status_t
917 _cairo_default_context_paint_with_alpha (void *abstract_cr,
920 cairo_default_context_t *cr = abstract_cr;
921 cairo_solid_pattern_t pattern;
922 cairo_status_t status;
925 if (CAIRO_ALPHA_IS_OPAQUE (alpha))
926 return _cairo_gstate_paint (cr->gstate);
928 if (CAIRO_ALPHA_IS_ZERO (alpha) &&
929 _cairo_operator_bounded_by_mask (cr->gstate->op)) {
930 return CAIRO_STATUS_SUCCESS;
933 _cairo_color_init_rgba (&color, 0., 0., 0., alpha);
934 _cairo_pattern_init_solid (&pattern, &color);
936 status = _cairo_gstate_mask (cr->gstate, &pattern.base);
937 _cairo_pattern_fini (&pattern.base);
942 static cairo_status_t
943 _cairo_default_context_mask (void *abstract_cr,
944 cairo_pattern_t *mask)
946 cairo_default_context_t *cr = abstract_cr;
948 return _cairo_gstate_mask (cr->gstate, mask);
951 static cairo_status_t
952 _cairo_default_context_stroke_preserve (void *abstract_cr)
954 cairo_default_context_t *cr = abstract_cr;
956 return _cairo_gstate_stroke (cr->gstate, cr->path);
959 static cairo_status_t
960 _cairo_default_context_stroke (void *abstract_cr)
962 cairo_default_context_t *cr = abstract_cr;
963 cairo_status_t status;
965 status = _cairo_gstate_stroke (cr->gstate, cr->path);
966 if (unlikely (status))
969 return _cairo_default_context_new_path (cr);
972 static cairo_status_t
973 _cairo_default_context_in_stroke (void *abstract_cr,
975 cairo_bool_t *inside)
977 cairo_default_context_t *cr = abstract_cr;
979 return _cairo_gstate_in_stroke (cr->gstate,
985 static cairo_status_t
986 _cairo_default_context_stroke_extents (void *abstract_cr,
987 double *x1, double *y1, double *x2, double *y2)
989 cairo_default_context_t *cr = abstract_cr;
991 return _cairo_gstate_stroke_extents (cr->gstate,
996 static cairo_status_t
997 _cairo_default_context_fill_preserve (void *abstract_cr)
999 cairo_default_context_t *cr = abstract_cr;
1001 return _cairo_gstate_fill (cr->gstate, cr->path);
1004 static cairo_status_t
1005 _cairo_default_context_fill (void *abstract_cr)
1007 cairo_default_context_t *cr = abstract_cr;
1008 cairo_status_t status;
1010 status = _cairo_gstate_fill (cr->gstate, cr->path);
1011 if (unlikely (status))
1014 return _cairo_default_context_new_path (cr);
1017 static cairo_status_t
1018 _cairo_default_context_in_fill (void *abstract_cr,
1020 cairo_bool_t *inside)
1022 cairo_default_context_t *cr = abstract_cr;
1024 *inside = _cairo_gstate_in_fill (cr->gstate,
1027 return CAIRO_STATUS_SUCCESS;
1030 static cairo_status_t
1031 _cairo_default_context_fill_extents (void *abstract_cr,
1032 double *x1, double *y1, double *x2, double *y2)
1034 cairo_default_context_t *cr = abstract_cr;
1036 return _cairo_gstate_fill_extents (cr->gstate,
1041 static cairo_status_t
1042 _cairo_default_context_clip_preserve (void *abstract_cr)
1044 cairo_default_context_t *cr = abstract_cr;
1046 return _cairo_gstate_clip (cr->gstate, cr->path);
1049 static cairo_status_t
1050 _cairo_default_context_clip (void *abstract_cr)
1052 cairo_default_context_t *cr = abstract_cr;
1053 cairo_status_t status;
1055 status = _cairo_gstate_clip (cr->gstate, cr->path);
1056 if (unlikely (status))
1059 return _cairo_default_context_new_path (cr);
1062 static cairo_status_t
1063 _cairo_default_context_in_clip (void *abstract_cr,
1065 cairo_bool_t *inside)
1067 cairo_default_context_t *cr = abstract_cr;
1069 *inside = _cairo_gstate_in_clip (cr->gstate, x, y);
1070 return CAIRO_STATUS_SUCCESS;
1073 static cairo_status_t
1074 _cairo_default_context_reset_clip (void *abstract_cr)
1076 cairo_default_context_t *cr = abstract_cr;
1078 return _cairo_gstate_reset_clip (cr->gstate);
1081 static cairo_status_t
1082 _cairo_default_context_clip_extents (void *abstract_cr,
1083 double *x1, double *y1, double *x2, double *y2)
1085 cairo_default_context_t *cr = abstract_cr;
1087 if (! _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2)) {
1094 return CAIRO_STATUS_SUCCESS;
1097 static cairo_rectangle_list_t *
1098 _cairo_default_context_copy_clip_rectangle_list (void *abstract_cr)
1100 cairo_default_context_t *cr = abstract_cr;
1102 return _cairo_gstate_copy_clip_rectangle_list (cr->gstate);
1105 static cairo_status_t
1106 _cairo_default_context_copy_page (void *abstract_cr)
1108 cairo_default_context_t *cr = abstract_cr;
1110 return _cairo_gstate_copy_page (cr->gstate);
1113 static cairo_status_t
1114 _cairo_default_context_show_page (void *abstract_cr)
1116 cairo_default_context_t *cr = abstract_cr;
1118 return _cairo_gstate_show_page (cr->gstate);
1121 static cairo_status_t
1122 _cairo_default_context_set_font_face (void *abstract_cr,
1123 cairo_font_face_t *font_face)
1125 cairo_default_context_t *cr = abstract_cr;
1127 return _cairo_gstate_set_font_face (cr->gstate, font_face);
1130 static cairo_font_face_t *
1131 _cairo_default_context_get_font_face (void *abstract_cr)
1133 cairo_default_context_t *cr = abstract_cr;
1134 cairo_font_face_t *font_face;
1135 cairo_status_t status;
1137 status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
1138 if (unlikely (status)) {
1139 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1140 return (cairo_font_face_t *) &_cairo_font_face_nil;
1146 static cairo_status_t
1147 _cairo_default_context_font_extents (void *abstract_cr,
1148 cairo_font_extents_t *extents)
1150 cairo_default_context_t *cr = abstract_cr;
1152 return _cairo_gstate_get_font_extents (cr->gstate, extents);
1155 static cairo_status_t
1156 _cairo_default_context_set_font_size (void *abstract_cr,
1159 cairo_default_context_t *cr = abstract_cr;
1161 return _cairo_gstate_set_font_size (cr->gstate, size);
1164 static cairo_status_t
1165 _cairo_default_context_set_font_matrix (void *abstract_cr,
1166 const cairo_matrix_t *matrix)
1168 cairo_default_context_t *cr = abstract_cr;
1170 return _cairo_gstate_set_font_matrix (cr->gstate, matrix);
1174 _cairo_default_context_get_font_matrix (void *abstract_cr,
1175 cairo_matrix_t *matrix)
1177 cairo_default_context_t *cr = abstract_cr;
1179 _cairo_gstate_get_font_matrix (cr->gstate, matrix);
1182 static cairo_status_t
1183 _cairo_default_context_set_font_options (void *abstract_cr,
1184 const cairo_font_options_t *options)
1186 cairo_default_context_t *cr = abstract_cr;
1188 _cairo_gstate_set_font_options (cr->gstate, options);
1189 return CAIRO_STATUS_SUCCESS;
1193 _cairo_default_context_get_font_options (void *abstract_cr,
1194 cairo_font_options_t *options)
1196 cairo_default_context_t *cr = abstract_cr;
1198 _cairo_gstate_get_font_options (cr->gstate, options);
1201 static cairo_status_t
1202 _cairo_default_context_set_scaled_font (void *abstract_cr,
1203 cairo_scaled_font_t *scaled_font)
1205 cairo_default_context_t *cr = abstract_cr;
1206 cairo_bool_t was_previous;
1207 cairo_status_t status;
1209 if (scaled_font == cr->gstate->scaled_font)
1210 return CAIRO_STATUS_SUCCESS;
1212 was_previous = scaled_font == cr->gstate->previous_scaled_font;
1214 status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
1215 if (unlikely (status))
1218 status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix);
1219 if (unlikely (status))
1222 _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options);
1225 cr->gstate->scaled_font = cairo_scaled_font_reference (scaled_font);
1227 return CAIRO_STATUS_SUCCESS;
1230 static cairo_scaled_font_t *
1231 _cairo_default_context_get_scaled_font (void *abstract_cr)
1233 cairo_default_context_t *cr = abstract_cr;
1234 cairo_scaled_font_t *scaled_font;
1235 cairo_status_t status;
1237 status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font);
1238 if (unlikely (status))
1239 return _cairo_scaled_font_create_in_error (status);
1244 static cairo_status_t
1245 _cairo_default_context_glyphs (void *abstract_cr,
1246 const cairo_glyph_t *glyphs,
1248 cairo_glyph_text_info_t *info)
1250 cairo_default_context_t *cr = abstract_cr;
1252 return _cairo_gstate_show_text_glyphs (cr->gstate, glyphs, num_glyphs, info);
1255 static cairo_status_t
1256 _cairo_default_context_glyph_path (void *abstract_cr,
1257 const cairo_glyph_t *glyphs,
1260 cairo_default_context_t *cr = abstract_cr;
1262 return _cairo_gstate_glyph_path (cr->gstate,
1267 static cairo_status_t
1268 _cairo_default_context_glyph_extents (void *abstract_cr,
1269 const cairo_glyph_t *glyphs,
1271 cairo_text_extents_t *extents)
1273 cairo_default_context_t *cr = abstract_cr;
1275 return _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents);
1278 static const cairo_backend_t _cairo_default_context_backend = {
1280 _cairo_default_context_destroy,
1282 _cairo_default_context_get_original_target,
1283 _cairo_default_context_get_current_target,
1285 _cairo_default_context_save,
1286 _cairo_default_context_restore,
1288 _cairo_default_context_push_group,
1289 _cairo_default_context_pop_group,
1291 _cairo_default_context_set_source_rgba,
1292 _cairo_default_context_set_source_surface,
1293 _cairo_default_context_set_source,
1294 _cairo_default_context_get_source,
1296 _cairo_default_context_set_antialias,
1297 _cairo_default_context_set_dash,
1298 _cairo_default_context_set_fill_rule,
1299 _cairo_default_context_set_line_cap,
1300 _cairo_default_context_set_line_join,
1301 _cairo_default_context_set_line_width,
1302 _cairo_default_context_set_miter_limit,
1303 _cairo_default_context_set_opacity,
1304 _cairo_default_context_set_operator,
1305 _cairo_default_context_set_tolerance,
1306 _cairo_default_context_get_antialias,
1307 _cairo_default_context_get_dash,
1308 _cairo_default_context_get_fill_rule,
1309 _cairo_default_context_get_line_cap,
1310 _cairo_default_context_get_line_join,
1311 _cairo_default_context_get_line_width,
1312 _cairo_default_context_get_miter_limit,
1313 _cairo_default_context_get_opacity,
1314 _cairo_default_context_get_operator,
1315 _cairo_default_context_get_tolerance,
1317 _cairo_default_context_translate,
1318 _cairo_default_context_scale,
1319 _cairo_default_context_rotate,
1320 _cairo_default_context_transform,
1321 _cairo_default_context_set_matrix,
1322 _cairo_default_context_set_identity_matrix,
1323 _cairo_default_context_get_matrix,
1324 _cairo_default_context_user_to_device,
1325 _cairo_default_context_user_to_device_distance,
1326 _cairo_default_context_device_to_user,
1327 _cairo_default_context_device_to_user_distance,
1329 _cairo_default_context_new_path,
1330 _cairo_default_context_new_sub_path,
1331 _cairo_default_context_move_to,
1332 _cairo_default_context_rel_move_to,
1333 _cairo_default_context_line_to,
1334 _cairo_default_context_rel_line_to,
1335 _cairo_default_context_curve_to,
1336 _cairo_default_context_rel_curve_to,
1338 NULL, /* rel-arc-to */
1339 _cairo_default_context_close_path,
1340 _cairo_default_context_arc,
1341 _cairo_default_context_rectangle,
1342 _cairo_default_context_path_extents,
1343 _cairo_default_context_has_current_point,
1344 _cairo_default_context_get_current_point,
1345 _cairo_default_context_copy_path,
1346 _cairo_default_context_copy_path_flat,
1347 _cairo_default_context_append_path,
1349 NULL, /* stroke-to-path */
1351 _cairo_default_context_clip,
1352 _cairo_default_context_clip_preserve,
1353 _cairo_default_context_in_clip,
1354 _cairo_default_context_clip_extents,
1355 _cairo_default_context_reset_clip,
1356 _cairo_default_context_copy_clip_rectangle_list,
1358 _cairo_default_context_paint,
1359 _cairo_default_context_paint_with_alpha,
1360 _cairo_default_context_mask,
1362 _cairo_default_context_stroke,
1363 _cairo_default_context_stroke_preserve,
1364 _cairo_default_context_in_stroke,
1365 _cairo_default_context_stroke_extents,
1367 _cairo_default_context_fill,
1368 _cairo_default_context_fill_preserve,
1369 _cairo_default_context_in_fill,
1370 _cairo_default_context_fill_extents,
1372 _cairo_default_context_set_font_face,
1373 _cairo_default_context_get_font_face,
1374 _cairo_default_context_set_font_size,
1375 _cairo_default_context_set_font_matrix,
1376 _cairo_default_context_get_font_matrix,
1377 _cairo_default_context_set_font_options,
1378 _cairo_default_context_get_font_options,
1379 _cairo_default_context_set_scaled_font,
1380 _cairo_default_context_get_scaled_font,
1381 _cairo_default_context_font_extents,
1383 _cairo_default_context_glyphs,
1384 _cairo_default_context_glyph_path,
1385 _cairo_default_context_glyph_extents,
1387 _cairo_default_context_copy_page,
1388 _cairo_default_context_show_page,
1392 _cairo_default_context_init (cairo_default_context_t *cr, void *target)
1394 _cairo_init (&cr->base, &_cairo_default_context_backend);
1395 _cairo_path_fixed_init (cr->path);
1397 cr->gstate = &cr->gstate_tail[0];
1398 cr->gstate_freelist = &cr->gstate_tail[1];
1399 cr->gstate_tail[1].next = NULL;
1401 return _cairo_gstate_init (cr->gstate, target);
1405 _cairo_default_context_create (void *target)
1407 cairo_default_context_t *cr;
1408 cairo_status_t status;
1410 cr = _freed_pool_get (&context_pool);
1411 if (unlikely (cr == NULL)) {
1412 cr = malloc (sizeof (cairo_default_context_t));
1413 if (unlikely (cr == NULL))
1414 return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1417 status = _cairo_default_context_init (cr, target);
1418 if (unlikely (status)) {
1419 _freed_pool_put (&context_pool, cr);
1420 return _cairo_create_in_error (status);