beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-cogl-context.c
blob0116b0a5a93fafbbf7a791d1f328221453a0f57d
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.
28 * Contributor(s):
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).
55 #include "cairoint.h"
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"
62 #include <glib.h>
64 static freed_pool_t context_pool;
66 void
67 _cairo_cogl_context_reset_static_data (void)
69 _freed_pool_reset (&context_pool);
72 static cairo_status_t
73 _cairo_cogl_context_rectangle_real (cairo_cogl_context_t *cr,
74 double x, double y,
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))
80 return 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))
123 return status;
126 cr->path_ctm_age++;
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))
138 return status;
141 cr->path_ctm_age++;
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))
153 return status;
156 cr->path_ctm_age++;
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))
168 return status;
171 cr->path_ctm_age++;
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))
183 return status;
186 cr->path_ctm_age++;
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))
198 return status;
201 cr->path_ctm_age++;
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))
213 return status;
216 cr->path_ctm_age++;
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))
229 return status;
232 status = cr->dev->backend_parent.new_path (abstract_cr);
233 if (unlikely (status))
234 return 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))
252 return status;
255 status = cr->dev->backend_parent.new_sub_path (abstract_cr);
256 if (unlikely (status))
257 return 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))
274 return status;
277 status = cr->dev->backend_parent.move_to (abstract_cr, x, y);
278 if (unlikely (status))
279 return 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))
297 return status;
300 status = cr->dev->backend_parent.line_to (abstract_cr, x, y);
301 if (unlikely (status))
302 return 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))
328 return status;
331 status = cr->dev->backend_parent.curve_to (abstract_cr, x1, y1, x2, y2, x3, y3);
332 if (unlikely (status))
333 return 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,
348 x1_fixed, y1_fixed,
349 x2_fixed, y2_fixed,
350 x3_fixed, y3_fixed);
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))
365 return status;
368 status = cr->dev->backend_parent.arc (abstract_cr, xc, yc, radius, angle1, angle2, forward);
369 if (unlikely (status))
370 return 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 */
376 if (radius <= 0.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))
383 return status;
385 status = _cairo_path_fixed_line_to (&cr->user_path, x_fixed, y_fixed);
386 if (unlikely (status))
387 return 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))
397 return status;
399 if (forward)
400 _cairo_arc_path (&cr->base.base, xc, yc, radius, angle1, angle2);
401 else
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))
417 return status;
420 status = cr->dev->backend_parent.rel_move_to (abstract_cr, dx, dy);
421 if (unlikely (status))
422 return 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))
440 return status;
443 status = cr->dev->backend_parent.rel_line_to (abstract_cr, dx, dy);
444 if (unlikely (status))
445 return 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))
472 return status;
475 status = cr->dev->backend_parent.rel_curve_to (abstract_cr, dx1, dy1, dx2, dy2, dx3, dy3);
476 if (unlikely (status))
477 return 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);
497 #if 0
498 static cairo_status_t
499 _cairo_cogl_context_arc_to (void *abstract_cr,
500 double x1, double y1,
501 double x2, double y2,
502 double radius)
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))
510 return status;
513 status = cr->dev->backend_parent.arc_to (abstract_cr, x1, y1, x2, y2, radius);
514 if (unlikely (status))
515 return status;
516 #warning "FIXME"
519 static cairo_status_t
520 _cairo_cogl_rel_arc_to (void *cr,
521 double dx1, double dy1,
522 double dx2, double dy2,
523 double radius)
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))
531 return status;
534 status = cr->dev->backend_parent.rel_arc_to (abstract_cr, dx1, dy2, dx2, dy2, radius);
535 if (unlikely (status))
536 return status;
537 #warning "FIXME"
539 #endif
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))
550 return status;
553 status = cr->dev->backend_parent.close_path (abstract_cr);
554 if (unlikely (status))
555 return 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,
565 double x, double y,
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;
573 #if 1
574 /* XXX: Since drawing rectangles is so common we have a
575 * fast-path for drawing a single rectangle. */
576 cr->x = x;
577 cr->y = y;
578 cr->width = width;
579 cr->height = height;
580 cr->path_is_rectangle = TRUE;
581 return CAIRO_STATUS_SUCCESS;
582 #endif
585 if (cr->path_is_rectangle) {
586 cairo_status_t status = _flush_cr_rectangle (cr);
587 if (unlikely (status))
588 return 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
597 * functions.
599 * For now we use this function to set side band data on the surface
600 * itself.
602 static void
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;
618 } else {
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,
633 cr->base.gstate->op,
634 cr->base.gstate->source,
635 cr->x,
636 cr->y,
637 cr->width,
638 cr->height,
639 &cr->base.gstate->ctm,
640 cr->base.gstate->clip);
641 if (status == CAIRO_STATUS_SUCCESS)
642 goto DONE;
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))
650 return status;
652 DONE:
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))
671 return 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))
687 return 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))
707 return 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))
720 return 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;
729 static void
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) */
749 cairo_t *
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;
794 #if 0
795 backend->arc_to = _cairo_cogl_context_arc_to;
796 backend->rel_arc_to = _cairo_cogl_context_rel_arc_to;
797 #endif
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;