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 © 2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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-error-private.h"
45 #include "cairo-arc-private.h"
46 #include "cairo-backend-private.h"
47 #include "cairo-default-context-private.h"
48 #include "cairo-freed-pool-private.h"
49 #include "cairo-gstate-private.h"
50 #include "cairo-image-surface-inline.h"
51 #include "cairo-path-private.h"
52 #include "cairo-pattern-private.h"
53 #include "cairo-skia-private.h"
54 #include "cairo-surface-backend-private.h"
57 #include <SkColorShader.h>
58 #include <SkGradientShader.h>
59 #include <SkDashPathEffect.h>
61 #if !defined(INFINITY)
62 #define INFINITY HUGE_VAL
65 #if (CAIRO_FIXED_BITS == 32) && (CAIRO_FIXED_FRAC_BITS == 16) && defined(SK_SCALAR_IS_FIXED)
66 # define CAIRO_FIXED_TO_SK_SCALAR(x) (x)
67 #elif defined(SK_SCALAR_IS_FIXED)
68 /* This can be done better, but this will do for now */
69 # define CAIRO_FIXED_TO_SK_SCALAR(x) SkFloatToScalar(_cairo_fixed_to_double(x))
71 # define CAIRO_FIXED_TO_SK_SCALAR(x) SkFloatToScalar(_cairo_fixed_to_double(x))
77 static freed_pool_t context_pool;
80 _cairo_skia_context_destroy (void *abstract_cr)
82 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
89 cairo_surface_destroy (&cr->target->image.base);
90 cairo_surface_destroy (&cr->original->image.base);
92 if (cr->source != NULL) {
93 if (cr->source_image != NULL) {
94 _cairo_surface_release_source_image (cr->source, cr->source_image, cr->source_extra);
95 cr->source_image = NULL;
97 cairo_surface_destroy (cr->source);
101 _cairo_fini (&cr->base);
103 _freed_pool_put (&context_pool, cr);
106 static cairo_surface_t *
107 _cairo_skia_context_get_original_target (void *abstract_cr)
109 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
111 return &cr->original->image.base;
114 static cairo_surface_t *
115 _cairo_skia_context_get_current_target (void *abstract_cr)
117 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
119 return &cr->target->image.base;
122 static cairo_status_t
123 _cairo_skia_context_save (void *abstract_cr)
125 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
128 return CAIRO_STATUS_SUCCESS;
131 static cairo_status_t
132 _cairo_skia_context_restore (void *abstract_cr)
134 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
136 cr->canvas->restore ();
137 return CAIRO_STATUS_SUCCESS;
140 static cairo_status_t
141 _cairo_skia_context_push_group (void *abstract_cr, cairo_content_t content)
143 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
144 cairo_surface_t *group_surface;
145 cairo_status_t status;
148 //clip = _cairo_gstate_get_clip (cr->gstate);
149 width = cr->target->image.width;
150 height = cr->target->image.height;
151 group_surface = cr->target->image.base.backend->create_similar (&cr->target->image.base,
152 content, width, height);
155 /* Set device offsets on the new surface so that logically it appears at
156 * the same location on the parent surface -- when we pop_group this,
157 * the source pattern will get fixed up for the appropriate target surface
158 * device offsets, so we want to set our own surface offsets from /that/,
159 * and not from the device origin. */
160 cairo_surface_set_device_offset (group_surface,
161 parent_surface->device_transform.x0 - extents.x,
162 parent_surface->device_transform.y0 - extents.y);
164 /* If we have a current path, we need to adjust it to compensate for
165 * the device offset just applied. */
166 _cairo_path_fixed_transform (cr->path,
167 &group_surface->device_transform);
170 status = _cairo_skia_context_save (cr);
171 if (unlikely (status)) {
172 cairo_surface_destroy (group_surface);
176 cairo_surface_destroy (&cr->target->image.base);
177 cr->target = (cairo_skia_surface_t *) group_surface;
179 return CAIRO_STATUS_SUCCESS;
182 static cairo_pattern_t *
183 _cairo_skia_context_pop_group (void *abstract_cr)
185 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
186 cairo_surface_t *group_surface;
187 cairo_pattern_t *group_pattern;
188 cairo_status_t status;
190 group_surface = cairo_surface_reference (&cr->target->image.base);
192 status = _cairo_skia_context_restore (cr);
193 if (unlikely (status)) {
194 group_pattern = _cairo_pattern_create_in_error (status);
198 group_pattern = cairo_pattern_create_for_surface (group_surface);
199 status = group_pattern->status;
200 if (unlikely (status))
204 _cairo_gstate_get_matrix (cr->gstate, &group_matrix);
205 /* Transform by group_matrix centered around device_transform so that when
206 * we call _cairo_gstate_copy_transformed_pattern the result is a pattern
207 * with a matrix equivalent to the device_transform of group_surface. */
208 if (_cairo_surface_has_device_transform (group_surface)) {
209 cairo_pattern_set_matrix (group_pattern, &group_surface->device_transform);
210 _cairo_pattern_transform (group_pattern, &group_matrix);
211 _cairo_pattern_transform (group_pattern, &group_surface->device_transform_inverse);
213 cairo_pattern_set_matrix (group_pattern, &group_matrix);
216 /* If we have a current path, we need to adjust it to compensate for
217 * the device offset just removed. */
218 _cairo_path_fixed_transform (cr->path,
219 &group_surface->device_transform_inverse);
223 cairo_surface_destroy (group_surface);
225 return group_pattern;
228 static inline cairo_surface_t *
229 surface_from_pattern (const cairo_pattern_t *pattern)
231 return (reinterpret_cast <const cairo_surface_pattern_t *> (pattern))->surface;
235 surface_to_sk_bitmap (cairo_surface_t *surface, SkBitmap& bitmap)
237 cairo_image_surface_t *img = (cairo_image_surface_t *) surface;
238 SkBitmap::Config config;
241 if (unlikely (! format_to_sk_config (img->format, config, opaque)))
245 bitmap.setConfig (config, img->width, img->height, img->stride);
246 bitmap.setIsOpaque (opaque);
247 bitmap.setPixels (img->data);
252 static inline SkMatrix
253 matrix_to_sk (const cairo_matrix_t& mat)
258 skm.set (SkMatrix::kMScaleX, SkFloatToScalar (mat.xx));
259 skm.set (SkMatrix::kMSkewX, SkFloatToScalar (mat.xy));
260 skm.set (SkMatrix::kMTransX, SkFloatToScalar (mat.x0));
261 skm.set (SkMatrix::kMSkewY, SkFloatToScalar (mat.yx));
262 skm.set (SkMatrix::kMScaleY, SkFloatToScalar (mat.yy));
263 skm.set (SkMatrix::kMTransY, SkFloatToScalar (mat.y0));
266 skm[6] = SkFloatToScalar (0.0);
267 skm[7] = SkFloatToScalar (0.0);
268 skm[8] = SkFloatToScalar (1.0); -- this isn't right, it wants a magic value in there that it'll set itself. It wants Sk_Fract1 (2.30), not Sk_Scalar1
274 static inline SkMatrix
275 matrix_inverse_to_sk (const cairo_matrix_t& mat)
277 cairo_matrix_t inv = mat;
278 cairo_status_t status = cairo_matrix_invert (&inv);
279 assert (status == CAIRO_STATUS_SUCCESS);
280 return matrix_to_sk (inv);
283 static SkShader::TileMode
284 extend_to_sk (cairo_extend_t extend)
286 static const SkShader::TileMode modeMap[] = {
287 SkShader::kClamp_TileMode, // NONE behaves like PAD, because noone wants NONE
288 SkShader::kRepeat_TileMode,
289 SkShader::kMirror_TileMode,
290 SkShader::kClamp_TileMode
293 return modeMap[extend];
296 static inline SkColor
297 color_to_sk (const cairo_color_t& c)
299 /* Need unpremultiplied 1-byte values */
300 return SkColorSetARGB ((U8CPU) (c.alpha * 255),
301 (U8CPU) (c.red * 255),
302 (U8CPU) (c.green * 255),
303 (U8CPU) (c.blue * 255));
306 static inline SkColor
307 color_stop_to_sk (const cairo_color_stop_t& c)
309 /* Need unpremultiplied 1-byte values */
310 return SkColorSetARGB ((U8CPU) (c.alpha * 255),
311 (U8CPU) (c.red * 255),
312 (U8CPU) (c.green * 255),
313 (U8CPU) (c.blue * 255));
317 source_to_sk_shader (cairo_skia_context_t *cr,
318 const cairo_pattern_t *pattern)
320 SkShader *shader = NULL;
322 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
323 cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
324 return new SkColorShader (color_to_sk (solid->color));
325 } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
326 cairo_surface_t *surface = surface_from_pattern (pattern);
328 cr->source = cairo_surface_reference (surface);
330 if (surface->type == CAIRO_SURFACE_TYPE_SKIA) {
331 cairo_skia_surface_t *esurf = (cairo_skia_surface_t *) surface;
333 shader = SkShader::CreateBitmapShader (*esurf->bitmap,
334 extend_to_sk (pattern->extend),
335 extend_to_sk (pattern->extend));
339 if (! _cairo_surface_is_image (surface)) {
340 cairo_status_t status;
342 status = _cairo_surface_acquire_source_image (surface,
348 surface = &cr->source_image->base;
351 if (unlikely (! surface_to_sk_bitmap (surface, bitmap)))
354 shader = SkShader::CreateBitmapShader (bitmap,
355 extend_to_sk (pattern->extend),
356 extend_to_sk (pattern->extend));
358 } else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR
359 /* || pattern->type == CAIRO_PATTERN_TYPE_RADIAL */)
361 cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
362 SkColor colors_stack[10];
363 SkScalar pos_stack[10];
364 SkColor *colors = colors_stack;
365 SkScalar *pos = pos_stack;
367 if (gradient->n_stops > 10) {
368 colors = new SkColor[gradient->n_stops];
369 pos = new SkScalar[gradient->n_stops];
372 for (unsigned int i = 0; i < gradient->n_stops; i++) {
373 pos[i] = CAIRO_FIXED_TO_SK_SCALAR (gradient->stops[i].offset);
374 colors[i] = color_stop_to_sk (gradient->stops[i].color);
377 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
378 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
381 points[0].set (SkFloatToScalar (linear->pd1.x),
382 SkFloatToScalar (linear->pd1.y));
383 points[1].set (SkFloatToScalar (linear->pd2.x),
384 SkFloatToScalar (linear->pd2.y));
385 shader = SkGradientShader::CreateLinear (points, colors, pos, gradient->n_stops,
386 extend_to_sk (pattern->extend));
388 // XXX todo -- implement real radial shaders in Skia
391 if (gradient->n_stops > 10) {
397 if (shader && ! _cairo_matrix_is_identity (&pattern->matrix))
398 shader->setLocalMatrix (matrix_inverse_to_sk (pattern->matrix));
404 pattern_filter_to_sk (const cairo_pattern_t *pattern)
406 switch (pattern->filter) {
407 case CAIRO_FILTER_GOOD:
408 case CAIRO_FILTER_BEST:
409 case CAIRO_FILTER_BILINEAR:
410 case CAIRO_FILTER_GAUSSIAN:
413 case CAIRO_FILTER_FAST:
414 case CAIRO_FILTER_NEAREST:
420 pattern_to_sk_color (const cairo_pattern_t *pattern, SkColor& color)
422 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
425 color = color_to_sk (((cairo_solid_pattern_t *) pattern)->color);
429 static cairo_status_t
430 _cairo_skia_context_set_source (void *abstract_cr,
431 cairo_pattern_t *source)
433 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
436 if (cr->source != NULL) {
437 if (cr->source_image != NULL) {
438 _cairo_surface_release_source_image (cr->source, cr->source_image, cr->source_extra);
439 cr->source_image = NULL;
441 cairo_surface_destroy (cr->source);
445 if (pattern_to_sk_color (source, color)) {
446 cr->paint->setColor (color);
448 SkShader *shader = source_to_sk_shader (cr, source);
449 if (shader == NULL) {
451 return CAIRO_STATUS_SUCCESS;
454 cr->paint->setShader (shader);
457 cr->paint->setFilterBitmap (pattern_filter_to_sk (source));
460 /* XXX change notification */
461 return CAIRO_STATUS_SUCCESS;
464 static cairo_status_t
465 _cairo_skia_context_set_source_rgba (void *abstract_cr, double red, double green, double blue, double alpha)
467 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
469 /* Need unpremultiplied 1-byte values */
470 cr->paint->setARGB ((U8CPU) (alpha * 255),
472 (U8CPU) (green * 255),
473 (U8CPU) (blue * 255));
474 return CAIRO_STATUS_SUCCESS;
477 static cairo_status_t
478 _cairo_skia_context_set_source_surface (void *abstract_cr,
479 cairo_surface_t *surface,
483 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
484 cairo_pattern_t *pattern;
485 cairo_matrix_t matrix;
486 cairo_status_t status;
488 if (surface->type == CAIRO_SURFACE_TYPE_SKIA) {
489 cairo_skia_surface_t *esurf = (cairo_skia_surface_t *) surface;
492 shader = SkShader::CreateBitmapShader (*esurf->bitmap,
493 SkShader::kClamp_TileMode, /* XXX */
494 SkShader::kClamp_TileMode);
496 cr->paint->setShader (shader);
499 cr->paint->setFilterBitmap (true);
501 return CAIRO_STATUS_SUCCESS;
504 pattern = cairo_pattern_create_for_surface (surface);
505 if (unlikely (pattern->status))
506 return pattern->status;
508 cairo_matrix_init_translate (&matrix, -x, -y);
509 cairo_pattern_set_matrix (pattern, &matrix);
511 status = _cairo_skia_context_set_source (cr, pattern);
512 cairo_pattern_destroy (pattern);
517 static cairo_pattern_t *
518 _cairo_skia_context_get_source (void *abstract_cr)
520 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
526 static cairo_status_t
527 _cairo_skia_context_set_tolerance (void *abstract_cr,
530 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
533 return CAIRO_STATUS_SUCCESS;
536 static inline SkXfermode::Mode
537 operator_to_sk (cairo_operator_t op)
539 static const SkXfermode::Mode modeMap[] = {
540 SkXfermode::kClear_Mode,
542 SkXfermode::kSrc_Mode,
543 SkXfermode::kSrcOver_Mode,
544 SkXfermode::kSrcIn_Mode,
545 SkXfermode::kSrcOut_Mode,
546 SkXfermode::kSrcATop_Mode,
548 SkXfermode::kDst_Mode,
549 SkXfermode::kDstOver_Mode,
550 SkXfermode::kDstIn_Mode,
551 SkXfermode::kDstOut_Mode,
552 SkXfermode::kDstATop_Mode,
554 SkXfermode::kXor_Mode,
555 SkXfermode::kPlus_Mode, // XXX Add?
556 SkXfermode::kPlus_Mode, // XXX SATURATE
558 SkXfermode::kPlus_Mode,
559 SkXfermode::kMultiply_Mode,
560 SkXfermode::kScreen_Mode,
561 SkXfermode::kOverlay_Mode,
562 SkXfermode::kDarken_Mode,
563 SkXfermode::kLighten_Mode,
564 SkXfermode::kColorDodge_Mode,
565 SkXfermode::kColorBurn_Mode,
566 SkXfermode::kHardLight_Mode,
567 SkXfermode::kSoftLight_Mode,
568 SkXfermode::kDifference_Mode,
569 SkXfermode::kExclusion_Mode,
571 SkXfermode::kSrcOver_Mode, // XXX: CAIRO_OPERATOR_HSL_HUE
572 SkXfermode::kSrcOver_Mode, // XXX: CAIRO_OPERATOR_HSL_SATURATION,
573 SkXfermode::kSrcOver_Mode, // XXX: CAIRO_OPERATOR_HSL_COLOR,
574 SkXfermode::kSrcOver_Mode, // XXX: CAIRO_OPERATOR_HSL_LUMINOSITY
580 static cairo_status_t
581 _cairo_skia_context_set_operator (void *abstract_cr, cairo_operator_t op)
583 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
585 cr->paint->setXfermodeMode (operator_to_sk (op));
586 return CAIRO_STATUS_SUCCESS;
589 static cairo_status_t
590 _cairo_skia_context_set_opacity (void *abstract_cr, double opacity)
592 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
595 return CAIRO_STATUS_SUCCESS;
598 static cairo_status_t
599 _cairo_skia_context_set_antialias (void *abstract_cr, cairo_antialias_t antialias)
601 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
603 cr->paint->setAntiAlias (antialias != CAIRO_ANTIALIAS_NONE);
604 return CAIRO_STATUS_SUCCESS;
607 static cairo_status_t
608 _cairo_skia_context_set_fill_rule (void *abstract_cr,
609 cairo_fill_rule_t fill_rule)
611 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
613 cr->path->setFillType (fill_rule == CAIRO_FILL_RULE_WINDING ? SkPath::kWinding_FillType : SkPath::kEvenOdd_FillType);
614 return CAIRO_STATUS_SUCCESS;
617 static cairo_status_t
618 _cairo_skia_context_set_line_width (void *abstract_cr,
621 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
623 cr->paint->setStrokeWidth (SkFloatToScalar (line_width));
624 return CAIRO_STATUS_SUCCESS;
627 static cairo_status_t
628 _cairo_skia_context_set_line_cap (void *abstract_cr,
629 cairo_line_cap_t line_cap)
631 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
632 static const SkPaint::Cap map[] = {
637 cr->paint->setStrokeCap (map[line_cap]);
638 return CAIRO_STATUS_SUCCESS;
641 static cairo_status_t
642 _cairo_skia_context_set_line_join (void *abstract_cr,
643 cairo_line_join_t line_join)
645 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
646 static const SkPaint::Join map[] = {
647 SkPaint::kMiter_Join,
648 SkPaint::kRound_Join,
651 cr->paint->setStrokeJoin (map[line_join]);
652 return CAIRO_STATUS_SUCCESS;
655 static cairo_status_t
656 _cairo_skia_context_set_dash (void *abstract_cr,
657 const double *dashes,
661 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
662 SkScalar intervals_static[20];
663 SkScalar *intervals = intervals_static;
665 if (num_dashes == 0) {
666 cr->paint->setPathEffect (NULL);
667 return CAIRO_STATUS_SUCCESS;
671 if ((num_dashes & 1) != 0) {
677 intervals = new SkScalar[num_dashes];
681 for (int j = 0; i < num_dashes; j++)
682 intervals[i++] = SkFloatToScalar (dashes[j]);
685 SkDashPathEffect *dash = new SkDashPathEffect (intervals, num_dashes, SkFloatToScalar (offset));
687 cr->paint->setPathEffect (dash);
690 return CAIRO_STATUS_SUCCESS;
693 static cairo_status_t
694 _cairo_skia_context_set_miter_limit (void *abstract_cr, double limit)
696 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
698 cr->paint->setStrokeMiter (SkFloatToScalar (limit));
699 return CAIRO_STATUS_SUCCESS;
702 static cairo_antialias_t
703 _cairo_skia_context_get_antialias (void *abstract_cr)
705 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
707 return cr->paint->isAntiAlias () ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE;
711 _cairo_skia_context_get_dash (void *abstract_cr,
716 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
722 static cairo_fill_rule_t
723 _cairo_skia_context_get_fill_rule (void *abstract_cr)
725 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
728 ft = cr->path->getFillType ();
729 if (ft == SkPath::kWinding_FillType)
730 return CAIRO_FILL_RULE_WINDING;
731 if (ft == SkPath::kEvenOdd_FillType)
732 return CAIRO_FILL_RULE_EVEN_ODD;;
735 return CAIRO_FILL_RULE_WINDING;
739 _cairo_skia_context_get_line_width (void *abstract_cr)
741 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
743 return /* ScalarToFloat */ cr->paint->getStrokeWidth ();
746 static cairo_line_cap_t
747 _cairo_skia_context_get_line_cap (void *abstract_cr)
749 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
750 static const cairo_line_cap_t map[] = {
752 CAIRO_LINE_CAP_ROUND,
753 CAIRO_LINE_CAP_SQUARE
755 return map[cr->paint->getStrokeCap ()];
758 static cairo_line_join_t
759 _cairo_skia_context_get_line_join (void *abstract_cr)
761 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
762 static const cairo_line_join_t map[] = {
763 CAIRO_LINE_JOIN_MITER,
764 CAIRO_LINE_JOIN_ROUND,
765 CAIRO_LINE_JOIN_BEVEL
767 return map[cr->paint->getStrokeJoin ()];
771 _cairo_skia_context_get_miter_limit (void *abstract_cr)
773 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
775 return /* SkScalarToFloat */ cr->paint->getStrokeMiter ();
778 static cairo_operator_t
779 _cairo_skia_context_get_operator (void *abstract_cr)
781 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
784 //cr->paint->getXfermode ();
785 return CAIRO_OPERATOR_OVER;
789 _cairo_skia_context_get_opacity (void *abstract_cr)
791 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
798 _cairo_skia_context_get_tolerance (void *abstract_cr)
800 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
803 return CAIRO_GSTATE_TOLERANCE_DEFAULT;
807 /* Current tranformation matrix */
809 static cairo_status_t
810 _cairo_skia_context_translate (void *abstract_cr,
814 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
816 cairo_matrix_translate (&cr->matrix, tx, ty);
817 return CAIRO_STATUS_SUCCESS;
820 static cairo_status_t
821 _cairo_skia_context_scale (void *abstract_cr,
825 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
827 cairo_matrix_scale (&cr->matrix, sx, sy);
828 return CAIRO_STATUS_SUCCESS;
831 static cairo_status_t
832 _cairo_skia_context_rotate (void *abstract_cr,
835 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
837 cairo_matrix_rotate (&cr->matrix, theta);
838 return CAIRO_STATUS_SUCCESS;
841 static cairo_status_t
842 _cairo_skia_context_transform (void *abstract_cr,
843 const cairo_matrix_t *matrix)
845 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
847 cairo_matrix_multiply (&cr->matrix, &cr->matrix, matrix);
848 return CAIRO_STATUS_SUCCESS;
851 static cairo_status_t
852 _cairo_skia_context_set_matrix (void *abstract_cr,
853 const cairo_matrix_t *matrix)
855 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
857 cr->matrix = *matrix;
858 return CAIRO_STATUS_SUCCESS;
861 static cairo_status_t
862 _cairo_skia_context_set_identity_matrix (void *abstract_cr)
864 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
866 cairo_matrix_init_identity (&cr->matrix);
867 return CAIRO_STATUS_SUCCESS;
871 _cairo_skia_context_get_matrix (void *abstract_cr,
872 cairo_matrix_t *matrix)
874 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
876 *matrix = cr->matrix;
880 _cairo_skia_context_user_to_device (void *abstract_cr,
884 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
886 cairo_matrix_transform_point (&cr->matrix, x, y);
890 _cairo_skia_context_user_to_device_distance (void *abstract_cr,
894 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
896 cairo_matrix_transform_distance (&cr->matrix, dx, dy);
900 _cairo_skia_context_device_to_user (void *abstract_cr,
904 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
905 cairo_matrix_t inverse;
906 cairo_status_t status;
908 inverse = cr->matrix;
909 status = cairo_matrix_invert (&inverse);
910 assert (CAIRO_STATUS_SUCCESS == status);
912 cairo_matrix_transform_point (&inverse, x, y);
916 _cairo_skia_context_device_to_user_distance (void *abstract_cr,
920 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
921 cairo_matrix_t inverse;
922 cairo_status_t status;
924 inverse = cr->matrix;
925 status = cairo_matrix_invert (&inverse);
926 assert (CAIRO_STATUS_SUCCESS == status);
928 cairo_matrix_transform_distance (&inverse, dx, dy);
931 /* Path constructor */
933 static cairo_status_t
934 _cairo_skia_context_new_path (void *abstract_cr)
936 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
939 return CAIRO_STATUS_SUCCESS;
942 static cairo_status_t
943 _cairo_skia_context_new_sub_path (void *abstract_cr)
945 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
947 cr->path->rMoveTo (0, 0); /* XXX */
948 return CAIRO_STATUS_SUCCESS;
952 user_to_device_point (cairo_skia_context_t *cr, double *x, double *y)
954 cairo_matrix_transform_point (&cr->matrix, x, y);
955 cairo_matrix_transform_point (&cr->target->image.base.device_transform, x, y);
959 user_to_device_distance (cairo_skia_context_t *cr, double *dx, double *dy)
961 cairo_matrix_transform_distance (&cr->matrix, dx, dy);
962 cairo_matrix_transform_distance (&cr->target->image.base.device_transform, dx, dy);
965 static cairo_status_t
966 _cairo_skia_context_move_to (void *abstract_cr, double x, double y)
968 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
970 user_to_device_point (cr, &x, &y);
971 cr->path->moveTo (SkFloatToScalar (x), SkFloatToScalar (y));
972 return CAIRO_STATUS_SUCCESS;
975 static cairo_status_t
976 _cairo_skia_context_line_to (void *abstract_cr, double x, double y)
978 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
980 user_to_device_point (cr, &x, &y);
981 cr->path->lineTo (SkFloatToScalar (x), SkFloatToScalar (y));
982 return CAIRO_STATUS_SUCCESS;
985 static cairo_status_t
986 _cairo_skia_context_curve_to (void *abstract_cr,
987 double x1, double y1,
988 double x2, double y2,
989 double x3, double y3)
991 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
993 user_to_device_point (cr, &x1, &y1);
994 user_to_device_point (cr, &x2, &y2);
995 user_to_device_point (cr, &x3, &y3);
996 cr->path->cubicTo (SkFloatToScalar (x1), SkFloatToScalar (y1),
997 SkFloatToScalar (x2), SkFloatToScalar (y2),
998 SkFloatToScalar (x3), SkFloatToScalar (y3));
999 return CAIRO_STATUS_SUCCESS;
1002 static cairo_status_t
1003 _cairo_skia_context_arc_to (void *abstract_cr,
1004 double x1, double y1,
1005 double x2, double y2,
1008 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1011 user_to_device_point (cr, &x1, &y1);
1012 user_to_device_point (cr, &x2, &y2);
1013 user_to_device_distance (cr, &radius, &radius);
1016 cr->path->arcTo (SkFloatToScalar (x1), SkFloatToScalar (y1),
1017 SkFloatToScalar (x2), SkFloatToScalar (y2),
1018 SkFloatToScalar (radius));
1019 return CAIRO_STATUS_SUCCESS;
1022 static cairo_status_t
1023 _cairo_skia_context_rel_move_to (void *abstract_cr, double dx, double dy)
1025 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1027 user_to_device_distance (cr, &dx, &dy);
1028 cr->path->rMoveTo (SkFloatToScalar (dx), SkFloatToScalar (dy));
1029 return CAIRO_STATUS_SUCCESS;
1032 static cairo_status_t
1033 _cairo_skia_context_rel_line_to (void *abstract_cr, double dx, double dy)
1035 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1037 user_to_device_distance (cr, &dx, &dy);
1038 cr->path->rLineTo (SkFloatToScalar (dx), SkFloatToScalar (dy));
1039 return CAIRO_STATUS_SUCCESS;
1042 static cairo_status_t
1043 _cairo_skia_context_rel_curve_to (void *abstract_cr,
1044 double dx1, double dy1,
1045 double dx2, double dy2,
1046 double dx3, double dy3)
1048 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1050 user_to_device_distance (cr, &dx1, &dy1);
1051 user_to_device_distance (cr, &dx2, &dy2);
1052 user_to_device_distance (cr, &dx3, &dy3);
1053 cr->path->rCubicTo (SkFloatToScalar (dx1), SkFloatToScalar (dy1),
1054 SkFloatToScalar (dx2), SkFloatToScalar (dy2),
1055 SkFloatToScalar (dx3), SkFloatToScalar (dy3));
1056 return CAIRO_STATUS_SUCCESS;
1059 static cairo_status_t
1060 _cairo_skia_context_rel_arc_to (void *abstract_cr,
1061 double dx1, double dy1,
1062 double dx2, double dy2,
1065 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1068 user_to_device_point (cr, &x1, &y1);
1069 user_to_device_point (cr, &x2, &y2);
1070 user_to_device_distance (cr, &radius, &radius);
1073 cr->path->arcTo (SkFloatToScalar (dx1), SkFloatToScalar (dy1),
1074 SkFloatToScalar (dx2), SkFloatToScalar (dy2),
1075 SkFloatToScalar (radius));
1076 return CAIRO_STATUS_SUCCESS;
1079 static cairo_status_t
1080 _cairo_skia_context_close_path (void *abstract_cr)
1082 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1085 return CAIRO_STATUS_SUCCESS;
1088 static cairo_status_t
1089 _cairo_skia_context_rectangle (void *abstract_cr,
1091 double width, double height)
1093 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1094 double x1, y1, x2, y2;
1096 /* XXX assume no rotation! */
1098 user_to_device_point (cr, &x1, &y1);
1100 x2 = x + width, y2 = y + height;
1101 user_to_device_point (cr, &x2, &y2);
1103 cr->path->addRect (SkFloatToScalar (x1), SkFloatToScalar (y1),
1104 SkFloatToScalar (x2), SkFloatToScalar (y2));
1105 return CAIRO_STATUS_SUCCESS;
1108 static cairo_status_t
1109 _cairo_skia_context_arc (void *abstract_cr,
1110 double xc, double yc, double radius,
1111 double angle1, double angle2,
1112 cairo_bool_t forward)
1114 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1115 cairo_status_t status;
1117 /* XXX cr->path->arc() */
1119 /* Do nothing, successfully, if radius is <= 0 */
1120 if (radius <= 0.0) {
1121 status = _cairo_skia_context_line_to (cr, xc, yc);
1122 if (unlikely (status))
1125 status = _cairo_skia_context_line_to (cr, xc, yc);
1126 if (unlikely (status))
1129 return CAIRO_STATUS_SUCCESS;
1132 status = _cairo_skia_context_line_to (cr,
1133 xc + radius * cos (angle1),
1134 yc + radius * sin (angle1));
1136 if (unlikely (status))
1140 _cairo_arc_path (&cr->base, xc, yc, radius, angle1, angle2);
1142 _cairo_arc_path_negative (&cr->base, xc, yc, radius, angle1, angle2);
1144 return CAIRO_STATUS_SUCCESS;
1148 _cairo_skia_context_path_extents (void *abstract_cr,
1154 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1157 rect = cr->path->getBounds ();
1160 /* XXX transform SkScalar rect to user */
1164 _cairo_skia_context_has_current_point (void *abstract_cr)
1166 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1172 _cairo_skia_context_get_current_point (void *abstract_cr,
1176 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1179 cr->path->getLastPt (&pt);
1180 //*x = SkScalarToFloat (pt.x);
1181 //*y = SkScalarToFloat (pt.y);
1182 //_cairo_gstate_backend_to_user (cr->gstate, x, y);
1187 static cairo_path_t *
1188 _cairo_skia_context_copy_path (void *abstract_cr)
1190 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1197 static cairo_path_t *
1198 _cairo_skia_context_copy_path_flat (void *abstract_cr)
1200 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1202 /* XXX iterate and decompose */
1207 static cairo_status_t
1208 _cairo_skia_context_append_path (void *abstract_cr,
1209 const cairo_path_t *path)
1211 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1213 // return _cairo_path_append_to_context (path, cr);
1214 return CAIRO_STATUS_SUCCESS;
1217 static cairo_status_t
1218 _cairo_skia_stroke_to_path (void *abstract_cr)
1220 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1222 cr->paint->setStyle (SkPaint::kStroke_Style);
1223 cr->paint->getFillPath (*cr->path, cr->path);
1224 return CAIRO_STATUS_SUCCESS;
1228 static cairo_status_t
1229 _cairo_skia_context_paint (void *abstract_cr)
1231 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1234 if (cr->source != NULL) {
1236 SkMatrix bitmapMatrix;
1238 if (cr->source->type == CAIRO_SURFACE_TYPE_SKIA) {
1239 cairo_skia_surface_t *esurf = (cairo_skia_surface_t *) cr->source->type;
1241 bitmap = *esurf->bitmap;
1243 surface_to_sk_bitmap (&cr->source_image->base, bitmap);
1246 // XXX pattern->matrix, pattern->filter, pattern->extend
1247 cr->canvas->drawBitmapMatrix (bitmap, bitmapMatrix, cr->paint);
1249 cr->canvas->drawPaint (*cr->paint);
1252 cr->canvas->drawPaint (*cr->paint);
1254 return CAIRO_STATUS_SUCCESS;
1257 static cairo_status_t
1258 _cairo_skia_context_paint_with_alpha (void *abstract_cr,
1261 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1262 cairo_status_t status;
1264 if (CAIRO_ALPHA_IS_OPAQUE (alpha))
1265 return _cairo_skia_context_paint (cr);
1267 cr->paint->setAlpha(SkScalarRound(255*alpha));
1268 status = _cairo_skia_context_paint (cr);
1269 cr->paint->setAlpha(255);
1274 static cairo_status_t
1275 _cairo_skia_context_mask (void *abstract_cr,
1276 cairo_pattern_t *mask)
1278 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1282 return CAIRO_STATUS_SUCCESS;
1285 static cairo_status_t
1286 _cairo_skia_context_stroke_preserve (void *abstract_cr)
1288 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1290 cr->paint->setStyle (SkPaint::kStroke_Style);
1292 /* XXX pen transformation? */
1293 //assert (_cairo_matrix_is_identity (&cr->matrix));
1294 cr->canvas->drawPath (*cr->path, *cr->paint);
1295 return CAIRO_STATUS_SUCCESS;
1298 static cairo_status_t
1299 _cairo_skia_context_stroke (void *abstract_cr)
1301 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1302 cairo_status_t status;
1304 status = _cairo_skia_context_stroke_preserve (cr);
1305 if (unlikely (status))
1308 return _cairo_skia_context_new_path (cr);
1311 static cairo_status_t
1312 _cairo_skia_context_in_stroke (void *abstract_cr,
1314 cairo_bool_t *inside)
1316 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1319 return CAIRO_STATUS_SUCCESS;
1322 static cairo_status_t
1323 _cairo_skia_context_stroke_extents (void *abstract_cr,
1324 double *x1, double *y1, double *x2, double *y2)
1326 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1329 return CAIRO_STATUS_SUCCESS;
1332 static cairo_status_t
1333 _cairo_skia_context_fill_preserve (void *abstract_cr)
1335 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1337 cr->paint->setStyle (SkPaint::kFill_Style);
1338 cr->canvas->drawPath (*cr->path, *cr->paint);
1339 return CAIRO_STATUS_SUCCESS;
1342 static cairo_status_t
1343 _cairo_skia_context_fill (void *abstract_cr)
1345 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1346 cairo_status_t status;
1348 status = _cairo_skia_context_fill_preserve (cr);
1349 if (unlikely (status))
1352 return _cairo_skia_context_new_path (cr);
1355 static cairo_status_t
1356 _cairo_skia_context_in_fill (void *abstract_cr,
1358 cairo_bool_t *inside)
1360 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1363 return CAIRO_STATUS_SUCCESS;
1366 static cairo_status_t
1367 _cairo_skia_context_fill_extents (void *abstract_cr,
1368 double *x1, double *y1, double *x2, double *y2)
1370 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1373 return CAIRO_STATUS_SUCCESS;
1376 static cairo_status_t
1377 _cairo_skia_context_clip_preserve (void *abstract_cr)
1379 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1381 cr->canvas->clipPath (*cr->path);
1382 return CAIRO_STATUS_SUCCESS;
1385 static cairo_status_t
1386 _cairo_skia_context_clip (void *abstract_cr)
1388 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1389 cairo_status_t status;
1391 status = _cairo_skia_context_clip_preserve (cr);
1392 if (unlikely (status))
1395 return _cairo_skia_context_new_path (cr);
1398 static cairo_status_t
1399 _cairo_skia_context_in_clip (void *abstract_cr,
1401 cairo_bool_t *inside)
1403 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1405 return CAIRO_STATUS_SUCCESS;
1408 static cairo_status_t
1409 _cairo_skia_context_reset_clip (void *abstract_cr)
1411 cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1412 SkRegion rgn(SkIRect::MakeWH (cr->target->bitmap->width (),
1413 cr->target->bitmap->height ()));
1415 cr->canvas->setClipRegion(rgn);
1416 return CAIRO_STATUS_SUCCESS;
1419 static cairo_status_t
1420 _cairo_skia_context_clip_extents (void *abstract_cr,
1421 double *x1, double *y1,
1422 double *x2, double *y2)
1424 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1427 return CAIRO_STATUS_SUCCESS;
1430 static cairo_rectangle_list_t *
1431 _cairo_skia_context_copy_clip_rectangle_list (void *abstract_cr)
1433 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1439 static cairo_status_t
1440 _cairo_skia_context_copy_page (void *abstract_cr)
1442 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1445 return CAIRO_STATUS_SUCCESS;
1448 static cairo_status_t
1449 _cairo_skia_context_show_page (void *abstract_cr)
1451 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1453 return CAIRO_STATUS_SUCCESS;
1456 static cairo_status_t
1457 _cairo_skia_context_set_font_face (void *abstract_cr,
1458 cairo_font_face_t *font_face)
1460 // cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1462 //return _cairo_gstate_set_font_face (cr->gstate, font_face);
1463 return CAIRO_STATUS_SUCCESS;
1466 static cairo_font_face_t *
1467 _cairo_skia_context_get_font_face (void *abstract_cr)
1469 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1475 static cairo_status_t
1476 _cairo_skia_context_font_extents (void *abstract_cr,
1477 cairo_font_extents_t *extents)
1479 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1482 return CAIRO_STATUS_SUCCESS;
1485 static cairo_status_t
1486 _cairo_skia_context_set_font_size (void *abstract_cr,
1489 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1492 return CAIRO_STATUS_SUCCESS;
1495 static cairo_status_t
1496 _cairo_skia_context_set_font_matrix (void *abstract_cr,
1497 const cairo_matrix_t *matrix)
1499 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1502 return CAIRO_STATUS_SUCCESS;
1506 _cairo_skia_context_get_font_matrix (void *abstract_cr,
1507 cairo_matrix_t *matrix)
1509 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1514 static cairo_status_t
1515 _cairo_skia_context_set_font_options (void *abstract_cr,
1516 const cairo_font_options_t *options)
1518 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1521 return CAIRO_STATUS_SUCCESS;
1525 _cairo_skia_context_get_font_options (void *abstract_cr,
1526 cairo_font_options_t *options)
1528 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1533 static cairo_status_t
1534 _cairo_skia_context_set_scaled_font (void *abstract_cr,
1535 cairo_scaled_font_t *scaled_font)
1537 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1540 return CAIRO_STATUS_SUCCESS;
1543 static cairo_scaled_font_t *
1544 _cairo_skia_context_get_scaled_font (void *abstract_cr)
1546 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1549 return _cairo_scaled_font_create_in_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1552 static cairo_status_t
1553 _cairo_skia_context_glyphs (void *abstract_cr,
1554 const cairo_glyph_t *glyphs,
1556 cairo_glyph_text_info_t *info)
1558 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1562 return CAIRO_STATUS_SUCCESS;
1565 static cairo_status_t
1566 _cairo_skia_context_glyph_path (void *abstract_cr,
1567 const cairo_glyph_t *glyphs,
1570 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1573 return CAIRO_STATUS_SUCCESS;
1576 static cairo_status_t
1577 _cairo_skia_context_glyph_extents (void *abstract_cr,
1578 const cairo_glyph_t *glyphs,
1580 cairo_text_extents_t *extents)
1582 //cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
1585 return CAIRO_STATUS_SUCCESS;
1588 static const cairo_backend_t _cairo_skia_context_backend = {
1590 _cairo_skia_context_destroy,
1592 _cairo_skia_context_get_original_target,
1593 _cairo_skia_context_get_current_target,
1595 _cairo_skia_context_save,
1596 _cairo_skia_context_restore,
1598 _cairo_skia_context_push_group,
1599 _cairo_skia_context_pop_group,
1601 _cairo_skia_context_set_source_rgba,
1602 _cairo_skia_context_set_source_surface,
1603 _cairo_skia_context_set_source,
1604 _cairo_skia_context_get_source,
1606 _cairo_skia_context_set_antialias,
1607 _cairo_skia_context_set_dash,
1608 _cairo_skia_context_set_fill_rule,
1609 _cairo_skia_context_set_line_cap,
1610 _cairo_skia_context_set_line_join,
1611 _cairo_skia_context_set_line_width,
1612 _cairo_skia_context_set_miter_limit,
1613 _cairo_skia_context_set_opacity,
1614 _cairo_skia_context_set_operator,
1615 _cairo_skia_context_set_tolerance,
1616 _cairo_skia_context_get_antialias,
1617 _cairo_skia_context_get_dash,
1618 _cairo_skia_context_get_fill_rule,
1619 _cairo_skia_context_get_line_cap,
1620 _cairo_skia_context_get_line_join,
1621 _cairo_skia_context_get_line_width,
1622 _cairo_skia_context_get_miter_limit,
1623 _cairo_skia_context_get_opacity,
1624 _cairo_skia_context_get_operator,
1625 _cairo_skia_context_get_tolerance,
1627 _cairo_skia_context_translate,
1628 _cairo_skia_context_scale,
1629 _cairo_skia_context_rotate,
1630 _cairo_skia_context_transform,
1631 _cairo_skia_context_set_matrix,
1632 _cairo_skia_context_set_identity_matrix,
1633 _cairo_skia_context_get_matrix,
1634 _cairo_skia_context_user_to_device,
1635 _cairo_skia_context_user_to_device_distance,
1636 _cairo_skia_context_device_to_user,
1637 _cairo_skia_context_device_to_user_distance,
1638 _cairo_skia_context_user_to_device, /* XXX backend */
1639 _cairo_skia_context_user_to_device_distance, /* XXX backend */
1640 _cairo_skia_context_device_to_user, /* XXX backend */
1641 _cairo_skia_context_device_to_user_distance, /* XXX backend */
1643 _cairo_skia_context_new_path,
1644 _cairo_skia_context_new_sub_path,
1645 _cairo_skia_context_move_to,
1646 _cairo_skia_context_rel_move_to,
1647 _cairo_skia_context_line_to,
1648 _cairo_skia_context_rel_line_to,
1649 _cairo_skia_context_curve_to,
1650 _cairo_skia_context_rel_curve_to,
1651 _cairo_skia_context_arc_to,
1652 _cairo_skia_context_rel_arc_to,
1653 _cairo_skia_context_close_path,
1654 _cairo_skia_context_arc,
1655 _cairo_skia_context_rectangle,
1656 _cairo_skia_context_path_extents,
1657 _cairo_skia_context_has_current_point,
1658 _cairo_skia_context_get_current_point,
1659 _cairo_skia_context_copy_path,
1660 _cairo_skia_context_copy_path_flat,
1661 _cairo_skia_context_append_path,
1663 _cairo_skia_stroke_to_path,
1665 _cairo_skia_context_clip,
1666 _cairo_skia_context_clip_preserve,
1667 _cairo_skia_context_in_clip,
1668 _cairo_skia_context_clip_extents,
1669 _cairo_skia_context_reset_clip,
1670 _cairo_skia_context_copy_clip_rectangle_list,
1672 _cairo_skia_context_paint,
1673 _cairo_skia_context_paint_with_alpha,
1674 _cairo_skia_context_mask,
1676 _cairo_skia_context_stroke,
1677 _cairo_skia_context_stroke_preserve,
1678 _cairo_skia_context_in_stroke,
1679 _cairo_skia_context_stroke_extents,
1681 _cairo_skia_context_fill,
1682 _cairo_skia_context_fill_preserve,
1683 _cairo_skia_context_in_fill,
1684 _cairo_skia_context_fill_extents,
1686 _cairo_skia_context_set_font_face,
1687 _cairo_skia_context_get_font_face,
1688 _cairo_skia_context_set_font_size,
1689 _cairo_skia_context_set_font_matrix,
1690 _cairo_skia_context_get_font_matrix,
1691 _cairo_skia_context_set_font_options,
1692 _cairo_skia_context_get_font_options,
1693 _cairo_skia_context_set_scaled_font,
1694 _cairo_skia_context_get_scaled_font,
1695 _cairo_skia_context_font_extents,
1697 _cairo_skia_context_glyphs,
1698 _cairo_skia_context_glyph_path,
1699 _cairo_skia_context_glyph_extents,
1701 _cairo_skia_context_copy_page,
1702 _cairo_skia_context_show_page,
1706 _cairo_skia_context_create (void *target)
1708 cairo_skia_surface_t *surface = (cairo_skia_surface_t *) target;
1709 cairo_skia_context_t *cr;
1711 cr = (cairo_skia_context_t *) _freed_pool_get (&context_pool);
1712 if (unlikely (cr == NULL)) {
1713 cr = new cairo_skia_context_t;
1714 if (unlikely (cr == NULL))
1715 return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1717 cr->path = new SkPath;
1718 cr->paint = new SkPaint;
1721 _cairo_init (&cr->base, &_cairo_skia_context_backend);
1724 cr->source_image = NULL;
1726 cr->paint->setStrokeWidth (SkFloatToScalar (2.0));
1728 cr->target = (cairo_skia_surface_t *) cairo_surface_reference ((cairo_surface_t *) target);
1729 cr->original = (cairo_skia_surface_t *) cairo_surface_reference ((cairo_surface_t *) target);
1730 cr->canvas = new SkCanvas (*surface->bitmap);
1731 cr->canvas->save ();
1733 cairo_matrix_init_identity (&cr->matrix);
1740 _cairo_skia_context_set_SkPaint (cairo_t *cr, SkPaint paint)
1746 _cairo_skia_context_set_SkPath (cairo_t *cr, SkPath path)