static SkBitmap * pattern_to_sk_bitmap (cairo_skia_surface_t *dst, const cairo_pattern_t *pattern, SkMatrix *matrix, cairo_image_surface_t **image, void **image_extra) { if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE) return NULL; if (pattern->extend != CAIRO_EXTEND_NONE) return NULL; cairo_surface_t *surface = surface_from_pattern (pattern); SkBitmap *bitmap; if (surface->type == CAIRO_SURFACE_TYPE_SKIA) { bitmap = new SkBitmap (*((cairo_skia_surface_t *) surface)->bitmap); } else { if (surface->type != CAIRO_SURFACE_TYPE_IMAGE) { cairo_status_t status; status = _cairo_surface_acquire_source_image (surface, image, image_extra); if (unlikely (status)) return NULL; surface = &(*image)->base; } bitmap = new SkBitmap; if (unlikely (! surface_to_sk_bitmap (surface, *bitmap))) return NULL; } *matrix = matrix_inverse_to_sk (pattern->matrix); return bitmap; }
static SkShader* source_to_sk_shader (cairo_skia_context_t *cr, const cairo_pattern_t *pattern) { SkShader *shader = NULL; if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern; return new SkColorShader (color_to_sk (solid->color)); } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_t *surface = surface_from_pattern (pattern); cr->source = cairo_surface_reference (surface); if (surface->type == CAIRO_SURFACE_TYPE_SKIA) { cairo_skia_surface_t *esurf = (cairo_skia_surface_t *) surface; shader = SkShader::CreateBitmapShader (*esurf->bitmap, extend_to_sk (pattern->extend), extend_to_sk (pattern->extend)); } else { SkBitmap bitmap; if (! _cairo_surface_is_image (surface)) { cairo_status_t status; status = _cairo_surface_acquire_source_image (surface, &cr->source_image, &cr->source_extra); if (status) return NULL; surface = &cr->source_image->base; } if (unlikely (! surface_to_sk_bitmap (surface, bitmap))) return NULL; shader = SkShader::CreateBitmapShader (bitmap, extend_to_sk (pattern->extend), extend_to_sk (pattern->extend)); } } else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR /* || pattern->type == CAIRO_PATTERN_TYPE_RADIAL */) { cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; SkColor colors_stack[10]; SkScalar pos_stack[10]; SkColor *colors = colors_stack; SkScalar *pos = pos_stack; if (gradient->n_stops > 10) { colors = new SkColor[gradient->n_stops]; pos = new SkScalar[gradient->n_stops]; } for (unsigned int i = 0; i < gradient->n_stops; i++) { pos[i] = CAIRO_FIXED_TO_SK_SCALAR (gradient->stops[i].offset); colors[i] = color_stop_to_sk (gradient->stops[i].color); } if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) { cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient; SkPoint points[2]; points[0].set (SkFloatToScalar (linear->pd1.x), SkFloatToScalar (linear->pd1.y)); points[1].set (SkFloatToScalar (linear->pd2.x), SkFloatToScalar (linear->pd2.y)); shader = SkGradientShader::CreateLinear (points, colors, pos, gradient->n_stops, extend_to_sk (pattern->extend)); } else { // XXX todo -- implement real radial shaders in Skia } if (gradient->n_stops > 10) { delete [] colors; delete [] pos; } } if (shader && ! _cairo_matrix_is_identity (&pattern->matrix)) shader->setLocalMatrix (matrix_inverse_to_sk (pattern->matrix)); return shader; }