1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2011 Intel Corporation.
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.og/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
29 * Robert Bragg <robert@linux.intel.com>
32 /* so long as we can verify that the ctm doesn't change multiple times
33 * during the construction of a path we can build a shadow
34 * #cairo_path_fixed_t in user coordinates that we can use to create a
35 * hash value for caching tessellations of that path.
37 * We need to hook into all the points where the ctm can be changed
38 * so we can bump a cr->path_ctm_age counter.
40 * We need to hook into all the points where the path can be modified
41 * so we can catch the start of a path and reset the cr->path_ctm_age
42 * counter at that point.
44 * When a draw operation is hit we can then check that the
45 * path_ctm_age == 0 and if so we create a hash of the path.
47 * We use this hash to lookup a #cairo_cogl_path_meta_t struct which
48 * may contain tessellated triangles for the path or may just contain
49 * a count of how many times the path has been re-seen (we only cache
50 * tessellated triangles if there is evidence that the path is being
51 * used multiple times because there is a cost involved in allocating
52 * a separate buffer for the triangles).
57 #include "cairo-cogl-context-private.h"
58 #include "cairo-freed-pool-private.h"
59 #include "cairo-arc-private.h"
60 #include "cairo-path-fixed-private.h"
64 static freed_pool_t context_pool
;
67 _cairo_cogl_context_reset_static_data (void)
69 _freed_pool_reset (&context_pool
);
73 _cairo_cogl_context_rectangle_real (cairo_cogl_context_t
*cr
,
75 double width
, double height
)
77 cairo_status_t status
;
78 status
= cr
->dev
->backend_parent
.rectangle (cr
, x
, y
, width
, height
);
79 if (unlikely (status
))
82 return _cairo_cogl_path_fixed_rectangle (&cr
->user_path
,
83 _cairo_fixed_from_double (x
),
84 _cairo_fixed_from_double (y
),
85 _cairo_fixed_from_double (width
),
86 _cairo_fixed_from_double (height
));
89 /* The idea here is that we have a simplified way of tracking rectangle paths
90 * because rectangles are perhaps the most common shape drawn with cairo.
92 * Basically we have a speculative store for a rectangle path that doesn't
93 * need to use the #cairo_path_fixed_t api to describe a rectangle in terms of
94 * (move_to,rel_line_to,rel_line_to,_rel_line_to,close) because if you profile
95 * heavy rectangle drawing with Cairo that process can be overly expensive.
97 * If the user asks to add more than just a rectangle to their current path
98 * then we "flush" any speculative rectangle stored into the current path
99 * before continuing to append their operations.
101 * In addition to the speculative store cairo-cogl also has a fast-path
102 * fill_rectangle drawing operation that further aims to minimize the cost
103 * of drawing rectangles.
105 static cairo_status_t
106 _flush_cr_rectangle (cairo_cogl_context_t
*cr
)
108 if (!cr
->path_is_rectangle
)
109 return CAIRO_STATUS_SUCCESS
;
111 cr
->path_is_rectangle
= FALSE
;
112 return _cairo_cogl_context_rectangle_real (cr
, cr
->x
, cr
->y
, cr
->width
, cr
->height
);
115 static cairo_status_t
116 _cairo_cogl_context_restore (void *abstract_cr
)
118 cairo_cogl_context_t
*cr
= abstract_cr
;
120 if (cr
->path_is_rectangle
) {
121 cairo_status_t status
= _flush_cr_rectangle (cr
);
122 if (unlikely (status
))
127 return cr
->dev
->backend_parent
.restore (abstract_cr
);
130 static cairo_status_t
131 _cairo_cogl_context_translate (void *abstract_cr
, double tx
, double ty
)
133 cairo_cogl_context_t
*cr
= abstract_cr
;
135 if (cr
->path_is_rectangle
) {
136 cairo_status_t status
= _flush_cr_rectangle (cr
);
137 if (unlikely (status
))
142 return cr
->dev
->backend_parent
.translate (abstract_cr
, tx
, ty
);
145 static cairo_status_t
146 _cairo_cogl_context_scale (void *abstract_cr
, double sx
, double sy
)
148 cairo_cogl_context_t
*cr
= abstract_cr
;
150 if (cr
->path_is_rectangle
) {
151 cairo_status_t status
= _flush_cr_rectangle (cr
);
152 if (unlikely (status
))
157 return cr
->dev
->backend_parent
.scale (abstract_cr
, sx
, sy
);
160 static cairo_status_t
161 _cairo_cogl_context_rotate (void *abstract_cr
, double theta
)
163 cairo_cogl_context_t
*cr
= abstract_cr
;
165 if (cr
->path_is_rectangle
) {
166 cairo_status_t status
= _flush_cr_rectangle (cr
);
167 if (unlikely (status
))
172 return cr
->dev
->backend_parent
.rotate (abstract_cr
, theta
);
175 static cairo_status_t
176 _cairo_cogl_context_transform (void *abstract_cr
, const cairo_matrix_t
*matrix
)
178 cairo_cogl_context_t
*cr
= abstract_cr
;
180 if (cr
->path_is_rectangle
) {
181 cairo_status_t status
= _flush_cr_rectangle (cr
);
182 if (unlikely (status
))
187 return cr
->dev
->backend_parent
.transform (abstract_cr
, matrix
);
190 static cairo_status_t
191 _cairo_cogl_context_set_matrix (void *abstract_cr
, const cairo_matrix_t
*matrix
)
193 cairo_cogl_context_t
*cr
= abstract_cr
;
195 if (cr
->path_is_rectangle
) {
196 cairo_status_t status
= _flush_cr_rectangle (cr
);
197 if (unlikely (status
))
202 return cr
->dev
->backend_parent
.set_matrix (abstract_cr
, matrix
);
205 static cairo_status_t
206 _cairo_cogl_context_set_identity_matrix (void *abstract_cr
)
208 cairo_cogl_context_t
*cr
= abstract_cr
;
210 if (cr
->path_is_rectangle
) {
211 cairo_status_t status
= _flush_cr_rectangle (cr
);
212 if (unlikely (status
))
217 return cr
->dev
->backend_parent
.set_identity_matrix (abstract_cr
);
220 static cairo_status_t
221 _cairo_cogl_context_new_path (void *abstract_cr
)
223 cairo_cogl_context_t
*cr
= abstract_cr
;
224 cairo_status_t status
;
226 if (cr
->path_is_rectangle
) {
227 status
= _flush_cr_rectangle (cr
);
228 if (unlikely (status
))
232 status
= cr
->dev
->backend_parent
.new_path (abstract_cr
);
233 if (unlikely (status
))
236 _cairo_path_fixed_fini (&cr
->user_path
);
237 _cairo_path_fixed_init (&cr
->user_path
);
238 cr
->path_is_rectangle
= FALSE
;
240 return CAIRO_STATUS_SUCCESS
;
243 static cairo_status_t
244 _cairo_cogl_context_new_sub_path (void *abstract_cr
)
246 cairo_cogl_context_t
*cr
= abstract_cr
;
247 cairo_status_t status
;
249 if (cr
->path_is_rectangle
) {
250 status
= _flush_cr_rectangle (cr
);
251 if (unlikely (status
))
255 status
= cr
->dev
->backend_parent
.new_sub_path (abstract_cr
);
256 if (unlikely (status
))
259 _cairo_path_fixed_new_sub_path (&cr
->user_path
);
261 return CAIRO_STATUS_SUCCESS
;
264 static cairo_status_t
265 _cairo_cogl_context_move_to (void *abstract_cr
, double x
, double y
)
267 cairo_cogl_context_t
*cr
= abstract_cr
;
268 cairo_status_t status
;
269 cairo_fixed_t x_fixed
, y_fixed
;
271 if (cr
->path_is_rectangle
) {
272 status
= _flush_cr_rectangle (cr
);
273 if (unlikely (status
))
277 status
= cr
->dev
->backend_parent
.move_to (abstract_cr
, x
, y
);
278 if (unlikely (status
))
281 x_fixed
= _cairo_fixed_from_double (x
);
282 y_fixed
= _cairo_fixed_from_double (y
);
284 return _cairo_path_fixed_move_to (&cr
->user_path
, x_fixed
, y_fixed
);
287 static cairo_status_t
288 _cairo_cogl_context_line_to (void *abstract_cr
, double x
, double y
)
290 cairo_cogl_context_t
*cr
= abstract_cr
;
291 cairo_status_t status
;
292 cairo_fixed_t x_fixed
, y_fixed
;
294 if (cr
->path_is_rectangle
) {
295 status
= _flush_cr_rectangle (cr
);
296 if (unlikely (status
))
300 status
= cr
->dev
->backend_parent
.line_to (abstract_cr
, x
, y
);
301 if (unlikely (status
))
304 x_fixed
= _cairo_fixed_from_double (x
);
305 y_fixed
= _cairo_fixed_from_double (y
);
307 if (cr
->user_path
.buf
.base
.num_ops
== 0)
308 cr
->path_ctm_age
= 0;
310 return _cairo_path_fixed_line_to (&cr
->user_path
, x_fixed
, y_fixed
);
313 static cairo_status_t
314 _cairo_cogl_context_curve_to (void *abstract_cr
,
315 double x1
, double y1
,
316 double x2
, double y2
,
317 double x3
, double y3
)
319 cairo_cogl_context_t
*cr
= abstract_cr
;
320 cairo_status_t status
;
321 cairo_fixed_t x1_fixed
, y1_fixed
;
322 cairo_fixed_t x2_fixed
, y2_fixed
;
323 cairo_fixed_t x3_fixed
, y3_fixed
;
325 if (cr
->path_is_rectangle
) {
326 status
= _flush_cr_rectangle (cr
);
327 if (unlikely (status
))
331 status
= cr
->dev
->backend_parent
.curve_to (abstract_cr
, x1
, y1
, x2
, y2
, x3
, y3
);
332 if (unlikely (status
))
335 x1_fixed
= _cairo_fixed_from_double (x1
);
336 y1_fixed
= _cairo_fixed_from_double (y1
);
338 x2_fixed
= _cairo_fixed_from_double (x2
);
339 y2_fixed
= _cairo_fixed_from_double (y2
);
341 x3_fixed
= _cairo_fixed_from_double (x3
);
342 y3_fixed
= _cairo_fixed_from_double (y3
);
344 if (cr
->user_path
.buf
.base
.num_ops
== 0)
345 cr
->path_ctm_age
= 0;
347 return _cairo_path_fixed_curve_to (&cr
->user_path
,
353 static cairo_status_t
354 _cairo_cogl_context_arc (void *abstract_cr
,
355 double xc
, double yc
, double radius
,
356 double angle1
, double angle2
,
357 cairo_bool_t forward
)
359 cairo_cogl_context_t
*cr
= abstract_cr
;
360 cairo_status_t status
;
362 if (cr
->path_is_rectangle
) {
363 status
= _flush_cr_rectangle (cr
);
364 if (unlikely (status
))
368 status
= cr
->dev
->backend_parent
.arc (abstract_cr
, xc
, yc
, radius
, angle1
, angle2
, forward
);
369 if (unlikely (status
))
372 if (cr
->user_path
.buf
.base
.num_ops
== 0)
373 cr
->path_ctm_age
= 0;
375 /* Do nothing, successfully, if radius is <= 0 */
377 cairo_fixed_t x_fixed
, y_fixed
;
379 x_fixed
= _cairo_fixed_from_double (xc
);
380 y_fixed
= _cairo_fixed_from_double (yc
);
381 status
= _cairo_path_fixed_line_to (&cr
->user_path
, x_fixed
, y_fixed
);
382 if (unlikely (status
))
385 status
= _cairo_path_fixed_line_to (&cr
->user_path
, x_fixed
, y_fixed
);
386 if (unlikely (status
))
389 return CAIRO_STATUS_SUCCESS
;
392 status
= _cairo_cogl_context_line_to (cr
,
393 xc
+ radius
* cos (angle1
),
394 yc
+ radius
* sin (angle1
));
396 if (unlikely (status
))
400 _cairo_arc_path (&cr
->base
.base
, xc
, yc
, radius
, angle1
, angle2
);
402 _cairo_arc_path_negative (&cr
->base
.base
, xc
, yc
, radius
, angle1
, angle2
);
404 return CAIRO_STATUS_SUCCESS
; /* any error will have already been set on cr */
407 static cairo_status_t
408 _cairo_cogl_context_rel_move_to (void *abstract_cr
, double dx
, double dy
)
410 cairo_cogl_context_t
*cr
= abstract_cr
;
411 cairo_status_t status
;
412 cairo_fixed_t dx_fixed
, dy_fixed
;
414 if (cr
->path_is_rectangle
) {
415 status
= _flush_cr_rectangle (cr
);
416 if (unlikely (status
))
420 status
= cr
->dev
->backend_parent
.rel_move_to (abstract_cr
, dx
, dy
);
421 if (unlikely (status
))
424 dx_fixed
= _cairo_fixed_from_double (dx
);
425 dy_fixed
= _cairo_fixed_from_double (dy
);
427 return _cairo_path_fixed_rel_move_to (&cr
->user_path
, dx_fixed
, dy_fixed
);
430 static cairo_status_t
431 _cairo_cogl_context_rel_line_to (void *abstract_cr
, double dx
, double dy
)
433 cairo_cogl_context_t
*cr
= abstract_cr
;
434 cairo_status_t status
;
435 cairo_fixed_t dx_fixed
, dy_fixed
;
437 if (cr
->path_is_rectangle
) {
438 status
= _flush_cr_rectangle (cr
);
439 if (unlikely (status
))
443 status
= cr
->dev
->backend_parent
.rel_line_to (abstract_cr
, dx
, dy
);
444 if (unlikely (status
))
447 dx_fixed
= _cairo_fixed_from_double (dx
);
448 dy_fixed
= _cairo_fixed_from_double (dy
);
450 if (cr
->user_path
.buf
.base
.num_ops
== 0)
451 cr
->path_ctm_age
= 0;
453 return _cairo_path_fixed_rel_line_to (&cr
->user_path
, dx_fixed
, dy_fixed
);
457 static cairo_status_t
458 _cairo_cogl_context_rel_curve_to (void *abstract_cr
,
459 double dx1
, double dy1
,
460 double dx2
, double dy2
,
461 double dx3
, double dy3
)
463 cairo_cogl_context_t
*cr
= abstract_cr
;
464 cairo_status_t status
;
465 cairo_fixed_t dx1_fixed
, dy1_fixed
;
466 cairo_fixed_t dx2_fixed
, dy2_fixed
;
467 cairo_fixed_t dx3_fixed
, dy3_fixed
;
469 if (cr
->path_is_rectangle
) {
470 status
= _flush_cr_rectangle (cr
);
471 if (unlikely (status
))
475 status
= cr
->dev
->backend_parent
.rel_curve_to (abstract_cr
, dx1
, dy1
, dx2
, dy2
, dx3
, dy3
);
476 if (unlikely (status
))
479 dx1_fixed
= _cairo_fixed_from_double (dx1
);
480 dy1_fixed
= _cairo_fixed_from_double (dy1
);
482 dx2_fixed
= _cairo_fixed_from_double (dx2
);
483 dy2_fixed
= _cairo_fixed_from_double (dy2
);
485 dx3_fixed
= _cairo_fixed_from_double (dx3
);
486 dy3_fixed
= _cairo_fixed_from_double (dy3
);
488 if (cr
->user_path
.buf
.base
.num_ops
== 0)
489 cr
->path_ctm_age
= 0;
491 return _cairo_path_fixed_rel_curve_to (&cr
->user_path
,
492 dx1_fixed
, dy1_fixed
,
493 dx2_fixed
, dy2_fixed
,
494 dx3_fixed
, dy3_fixed
);
498 static cairo_status_t
499 _cairo_cogl_context_arc_to (void *abstract_cr
,
500 double x1
, double y1
,
501 double x2
, double y2
,
504 cairo_cogl_context_t
*cr
= abstract_cr
;
505 cairo_status_t status
;
507 if (cr
->path_is_rectangle
) {
508 status
= _flush_cr_rectangle (cr
);
509 if (unlikely (status
))
513 status
= cr
->dev
->backend_parent
.arc_to (abstract_cr
, x1
, y1
, x2
, y2
, radius
);
514 if (unlikely (status
))
519 static cairo_status_t
520 _cairo_cogl_rel_arc_to (void *cr
,
521 double dx1
, double dy1
,
522 double dx2
, double dy2
,
525 cairo_cogl_context_t
*cr
= abstract_cr
;
526 cairo_status_t status
;
528 if (cr
->path_is_rectangle
) {
529 status
= _flush_cr_rectangle (cr
);
530 if (unlikely (status
))
534 status
= cr
->dev
->backend_parent
.rel_arc_to (abstract_cr
, dx1
, dy2
, dx2
, dy2
, radius
);
535 if (unlikely (status
))
541 static cairo_status_t
542 _cairo_cogl_context_close_path (void *abstract_cr
)
544 cairo_cogl_context_t
*cr
= abstract_cr
;
545 cairo_status_t status
;
547 if (cr
->path_is_rectangle
) {
548 status
= _flush_cr_rectangle (cr
);
549 if (unlikely (status
))
553 status
= cr
->dev
->backend_parent
.close_path (abstract_cr
);
554 if (unlikely (status
))
557 if (cr
->user_path
.buf
.base
.num_ops
== 0)
558 cr
->path_ctm_age
= 0;
560 return _cairo_path_fixed_close_path (&cr
->user_path
);
563 static cairo_status_t
564 _cairo_cogl_context_rectangle (void *abstract_cr
,
566 double width
, double height
)
568 cairo_cogl_context_t
*cr
= abstract_cr
;
570 if (cr
->user_path
.buf
.base
.num_ops
== 0) {
571 cr
->path_ctm_age
= 0;
574 /* XXX: Since drawing rectangles is so common we have a
575 * fast-path for drawing a single rectangle. */
580 cr
->path_is_rectangle
= TRUE
;
581 return CAIRO_STATUS_SUCCESS
;
585 if (cr
->path_is_rectangle
) {
586 cairo_status_t status
= _flush_cr_rectangle (cr
);
587 if (unlikely (status
))
591 return _cairo_cogl_context_rectangle_real (cr
, x
, y
, width
, height
);
594 /* Since the surface backend drawing operator functions don't get
595 * passed the current #cairo_t context we don't have a good way
596 * to get our user-coordinates path into our surface operator
599 * For now we use this function to set side band data on the surface
603 _cairo_cogl_surface_set_side_band_state (cairo_cogl_surface_t
*surface
,
604 cairo_cogl_context_t
*cr
)
607 if (cr
->path_ctm_age
<= 1) {
608 surface
->user_path
= &cr
->user_path
;
609 surface
->ctm
= &cr
->base
.gstate
->ctm
;
610 surface
->ctm_inverse
= &cr
->base
.gstate
->ctm_inverse
;
611 surface
->path_is_rectangle
= cr
->path_is_rectangle
;
612 if (surface
->path_is_rectangle
) {
613 surface
->path_rectangle_x
= cr
->x
;
614 surface
->path_rectangle_y
= cr
->y
;
615 surface
->path_rectangle_width
= cr
->width
;
616 surface
->path_rectangle_height
= cr
->height
;
619 surface
->user_path
= NULL
;
620 surface
->path_is_rectangle
= FALSE
;
624 static cairo_status_t
625 _cairo_cogl_context_fill (void *abstract_cr
)
627 cairo_cogl_context_t
*cr
= abstract_cr
;
628 cairo_status_t status
;
629 cairo_cogl_surface_t
*surface
= (cairo_cogl_surface_t
*)cr
->base
.gstate
->target
;
631 if (cr
->path_is_rectangle
) {
632 status
= _cairo_cogl_surface_fill_rectangle (cr
->base
.gstate
->target
,
634 cr
->base
.gstate
->source
,
639 &cr
->base
.gstate
->ctm
,
640 cr
->base
.gstate
->clip
);
641 if (status
== CAIRO_STATUS_SUCCESS
)
643 _flush_cr_rectangle (cr
);
646 _cairo_cogl_surface_set_side_band_state (surface
, cr
);
648 status
= cr
->dev
->backend_parent
.fill (abstract_cr
);
649 if (unlikely (status
))
653 _cairo_path_fixed_fini (&cr
->user_path
);
654 _cairo_path_fixed_init (&cr
->user_path
);
655 cr
->path_is_rectangle
= FALSE
;
657 return CAIRO_STATUS_SUCCESS
;
660 static cairo_status_t
661 _cairo_cogl_context_fill_preserve (void *abstract_cr
)
663 cairo_cogl_context_t
*cr
= abstract_cr
;
664 cairo_status_t status
;
665 cairo_cogl_surface_t
*surface
= (cairo_cogl_surface_t
*)cr
->base
.gstate
->target
;
667 _cairo_cogl_surface_set_side_band_state (surface
, cr
);
669 status
= cr
->dev
->backend_parent
.fill_preserve (abstract_cr
);
670 if (unlikely (status
))
673 return CAIRO_STATUS_SUCCESS
;
676 static cairo_status_t
677 _cairo_cogl_context_stroke (void *abstract_cr
)
679 cairo_cogl_context_t
*cr
= abstract_cr
;
680 cairo_status_t status
;
681 cairo_cogl_surface_t
*surface
= (cairo_cogl_surface_t
*)cr
->base
.gstate
->target
;
683 _cairo_cogl_surface_set_side_band_state (surface
, cr
);
685 status
= cr
->dev
->backend_parent
.stroke (abstract_cr
);
686 if (unlikely (status
))
689 _cairo_path_fixed_fini (&cr
->user_path
);
690 _cairo_path_fixed_init (&cr
->user_path
);
691 cr
->path_is_rectangle
= FALSE
;
693 return CAIRO_STATUS_SUCCESS
;
696 static cairo_status_t
697 _cairo_cogl_context_stroke_preserve (void *abstract_cr
)
699 cairo_cogl_context_t
*cr
= abstract_cr
;
700 cairo_status_t status
;
701 cairo_cogl_surface_t
*surface
= (cairo_cogl_surface_t
*)cr
->base
.gstate
->target
;
703 _cairo_cogl_surface_set_side_band_state (surface
, cr
);
705 status
= cr
->dev
->backend_parent
.stroke_preserve (abstract_cr
);
706 if (unlikely (status
))
709 return CAIRO_STATUS_SUCCESS
;
712 static cairo_status_t
713 _cairo_cogl_context_clip (void *abstract_cr
)
715 cairo_cogl_context_t
*cr
= abstract_cr
;
716 cairo_status_t status
;
718 status
= cr
->dev
->backend_parent
.clip (abstract_cr
);
719 if (unlikely (status
))
722 _cairo_path_fixed_fini (&cr
->user_path
);
723 _cairo_path_fixed_init (&cr
->user_path
);
724 cr
->path_is_rectangle
= FALSE
;
726 return CAIRO_STATUS_SUCCESS
;
730 _cairo_cogl_context_destroy (void *abstract_cr
)
732 cairo_cogl_context_t
*cr
= abstract_cr
;
734 _cairo_default_context_fini (&cr
->base
);
736 _cairo_path_fixed_fini (&cr
->user_path
);
738 /* mark the context as invalid to protect against misuse */
739 cr
->base
.base
.status
= CAIRO_STATUS_NULL_POINTER
;
740 _freed_pool_put (&context_pool
, cr
);
743 /* We want to hook into the frontend of the path construction APIs so
744 * we can build up a path description in user coordinates instead of
745 * backend coordinates so that we can recognize user coordinate
746 * rectangles and so we can hash a user path independent of its
747 * transform. (With some care to catch unusual cases where the ctm
748 * changes mid-path) */
750 _cairo_cogl_context_create (void *target
)
752 cairo_cogl_surface_t
*surface
= target
;
753 cairo_cogl_context_t
*cr
;
754 cairo_status_t status
;
756 cr
= _freed_pool_get (&context_pool
);
757 if (unlikely (cr
== NULL
)) {
758 cr
= malloc (sizeof (cairo_cogl_context_t
));
759 if (unlikely (cr
== NULL
))
760 return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
763 status
= _cairo_default_context_init (&cr
->base
, target
);
764 if (unlikely (status
)) {
765 _freed_pool_put (&context_pool
, cr
);
766 return _cairo_create_in_error (status
);
769 cr
->dev
= (cairo_cogl_device_t
*)surface
->base
.device
;
771 if (unlikely (cr
->dev
->backend_vtable_initialized
== FALSE
)) {
772 cairo_backend_t
*backend
= &cr
->dev
->backend
;
773 memcpy (backend
, cr
->base
.base
.backend
, sizeof (cairo_backend_t
));
774 memcpy (&cr
->dev
->backend_parent
, cr
->base
.base
.backend
, sizeof (cairo_backend_t
));
776 backend
->destroy
= _cairo_cogl_context_destroy
;
778 backend
->restore
= _cairo_cogl_context_restore
;
779 backend
->translate
= _cairo_cogl_context_translate
;
780 backend
->scale
= _cairo_cogl_context_scale
;
781 backend
->rotate
= _cairo_cogl_context_rotate
;
782 backend
->transform
= _cairo_cogl_context_transform
;
783 backend
->set_matrix
= _cairo_cogl_context_set_matrix
;
784 backend
->set_identity_matrix
= _cairo_cogl_context_set_identity_matrix
;
786 backend
->new_path
= _cairo_cogl_context_new_path
;
787 backend
->new_sub_path
= _cairo_cogl_context_new_sub_path
;
788 backend
->move_to
= _cairo_cogl_context_move_to
;
789 backend
->rel_move_to
= _cairo_cogl_context_rel_move_to
;
790 backend
->line_to
= _cairo_cogl_context_line_to
;
791 backend
->rel_line_to
= _cairo_cogl_context_rel_line_to
;
792 backend
->curve_to
= _cairo_cogl_context_curve_to
;
793 backend
->rel_curve_to
= _cairo_cogl_context_rel_curve_to
;
795 backend
->arc_to
= _cairo_cogl_context_arc_to
;
796 backend
->rel_arc_to
= _cairo_cogl_context_rel_arc_to
;
798 backend
->close_path
= _cairo_cogl_context_close_path
;
799 //backend->arc = _cairo_cogl_context_arc;
800 backend
->rectangle
= _cairo_cogl_context_rectangle
;
802 /* Try to automatically catch if any new path APIs are added that mean
803 * we may need to overload more functions... */
804 assert (((char *)&backend
->path_extents
- (char *)&backend
->device_to_user_distance
)
805 == (sizeof (void *) * 14));
807 backend
->fill
= _cairo_cogl_context_fill
;
808 backend
->fill_preserve
= _cairo_cogl_context_fill_preserve
;
809 backend
->stroke
= _cairo_cogl_context_stroke
;
810 backend
->stroke_preserve
= _cairo_cogl_context_stroke_preserve
;
811 backend
->clip
= _cairo_cogl_context_clip
;
813 cr
->dev
->backend_vtable_initialized
= TRUE
;
816 cr
->base
.base
.backend
= &cr
->dev
->backend
;
818 _cairo_path_fixed_init (&cr
->user_path
);
819 cr
->path_is_rectangle
= FALSE
;
821 return &cr
->base
.base
;