cairo_surface_t * _cairo_surface_fallback_snapshot (cairo_surface_t *surface) { cairo_surface_t *snapshot; cairo_status_t status; cairo_pattern_union_t pattern; cairo_image_surface_t *image; void *image_extra; status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); if (status) return _cairo_surface_create_in_error (status); snapshot = cairo_image_surface_create (image->format, image->width, image->height); if (cairo_surface_status (snapshot)) { _cairo_surface_release_source_image (surface, image, image_extra); return snapshot; } _cairo_pattern_init_for_surface (&pattern.surface, &image->base); status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, &pattern.base, NULL, snapshot, 0, 0, 0, 0, 0, 0, image->width, image->height); _cairo_pattern_fini (&pattern.base); _cairo_surface_release_source_image (surface, image, image_extra); if (status) { cairo_surface_destroy (snapshot); return _cairo_surface_create_in_error (status); } snapshot->device_transform = surface->device_transform; snapshot->device_transform_inverse = surface->device_transform_inverse; snapshot->is_snapshot = TRUE; return snapshot; }
cairo_surface_t * _cairo_surface_fallback_snapshot (cairo_surface_t *surface) { cairo_surface_t *snapshot; cairo_status_t status; cairo_format_t format; cairo_surface_pattern_t pattern; cairo_image_surface_t *image; void *image_extra; status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); if (unlikely (status)) return _cairo_surface_create_in_error (status); format = image->format; if (format == CAIRO_FORMAT_INVALID) { /* Non-standard images formats can be generated when retrieving * images from unusual xservers, for example. */ format = _cairo_format_from_content (image->base.content); } snapshot = cairo_image_surface_create (format, image->width, image->height); if (cairo_surface_status (snapshot)) { _cairo_surface_release_source_image (surface, image, image_extra); return snapshot; } _cairo_pattern_init_for_surface (&pattern, &image->base); status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, &pattern.base, NULL, snapshot, 0, 0, 0, 0, 0, 0, image->width, image->height); _cairo_pattern_fini (&pattern.base); _cairo_surface_release_source_image (surface, image, image_extra); if (unlikely (status)) { cairo_surface_destroy (snapshot); return _cairo_surface_create_in_error (status); } return snapshot; }
static cairo_status_t _cairo_skia_context_set_source (void *abstract_cr, cairo_pattern_t *source) { cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr; SkColor color; if (cr->source != NULL) { if (cr->source_image != NULL) { _cairo_surface_release_source_image (cr->source, cr->source_image, cr->source_extra); cr->source_image = NULL; } cairo_surface_destroy (cr->source); cr->source = NULL; } if (pattern_to_sk_color (source, color)) { cr->paint->setColor (color); } else { SkShader *shader = source_to_sk_shader (cr, source); if (shader == NULL) { UNSUPPORTED; return CAIRO_STATUS_SUCCESS; } cr->paint->setShader (shader); shader->unref (); cr->paint->setFilterBitmap (pattern_filter_to_sk (source)); } /* XXX change notification */ return CAIRO_STATUS_SUCCESS; }
static cairo_int_status_t _cairo_type3_glyph_surface_paint (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source) { cairo_type3_glyph_surface_t *surface = abstract_surface; cairo_surface_pattern_t *pattern; cairo_image_surface_t *image; void *image_extra; cairo_status_t status; if (source->type != CAIRO_PATTERN_TYPE_SURFACE) return CAIRO_INT_STATUS_IMAGE_FALLBACK; pattern = (cairo_surface_pattern_t *) source; status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); if (status) goto fail; status = _cairo_type3_glyph_surface_emit_image_pattern (surface, image, &pattern->base.matrix); fail: _cairo_surface_release_source_image (pattern->surface, image, image_extra); return status; }
static void _cairo_skia_context_destroy (void *abstract_cr) { cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr; cr->path->reset (); cr->paint->reset (); delete cr->canvas; cairo_surface_destroy (&cr->target->image.base); cairo_surface_destroy (&cr->original->image.base); if (cr->source != NULL) { if (cr->source_image != NULL) { _cairo_surface_release_source_image (cr->source, cr->source_image, cr->source_extra); cr->source_image = NULL; } cairo_surface_destroy (cr->source); cr->source = NULL; } _cairo_fini (&cr->base); _freed_pool_put (&context_pool, cr); }
void _cairo_surface_wrapper_release_source_image (cairo_surface_wrapper_t *wrapper, cairo_image_surface_t *image, void *image_extra) { _cairo_surface_release_source_image (wrapper->target, image, image_extra); }
static cairo_status_t _cairo_xml_emit_surface (cairo_xml_t *xml, const cairo_surface_pattern_t *pattern) { cairo_surface_t *source = pattern->surface; cairo_status_t status; if (_cairo_surface_is_recording (source)) { status = cairo_xml_for_recording_surface (&xml->base, source); } else { cairo_image_surface_t *image; void *image_extra; status = _cairo_surface_acquire_source_image (source, &image, &image_extra); if (unlikely (status)) return status; status = _cairo_xml_emit_image (xml, image); _cairo_surface_release_source_image (source, image, image_extra); } return status; }
static void _cairo_surface_snapshot_release_source_image (void *abstract_surface, cairo_image_surface_t *image, void *extra) { cairo_surface_snapshot_t *surface = abstract_surface; _cairo_surface_release_source_image (surface->target, image, extra); }
static void _test_fallback_surface_release_source_image (void *abstract_surface, cairo_image_surface_t *image, void *image_extra) { test_fallback_surface_t *surface = abstract_surface; _cairo_surface_release_source_image (surface->backing, image, image_extra); }
static cairo_int_status_t _cairo_skia_surface_paint (void *asurface, cairo_operator_t op, const cairo_pattern_t *source, cairo_clip_t *clip) { cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface; cairo_image_surface_t *image = NULL; cairo_status_t status; void *image_extra; SkColor color; status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); if (unlikely (status)) return (cairo_int_status_t) status; if (pattern_to_sk_color (source, color)) { surface->canvas->drawColor (color, operator_to_sk (op)); return CAIRO_INT_STATUS_SUCCESS; } SkMatrix bitmapMatrix; SkBitmap *bitmap = pattern_to_sk_bitmap (surface, source, &bitmapMatrix, &image, &image_extra); SkShader *shader = NULL; if (!bitmap) shader = pattern_to_sk_shader (surface, source, &image, &image_extra); if (!bitmap && !shader) return UNSUPPORTED("pattern to bitmap and shader conversion"); SkPaint paint; paint.setFilterBitmap (pattern_filter_to_sk (source)); paint.setXfermodeMode (operator_to_sk (op)); if (shader) { paint.setShader (shader); surface->canvas->drawPaint (paint); } else { surface->canvas->drawBitmapMatrix (*bitmap, bitmapMatrix, &paint); } if (bitmap) delete bitmap; if (shader) shader->unref (); if (image != NULL) { _cairo_surface_release_source_image (&surface->base, image, image_extra); } return CAIRO_INT_STATUS_SUCCESS; }
static void _cairo_surface_snapshot_release_source_image (void *abstract_surface, cairo_image_surface_t *image, void *_extra) { struct snapshot_extra *extra = _extra; _cairo_surface_release_source_image (extra->target, image, extra->extra); cairo_surface_destroy (extra->target); free (extra); }
static void _cairo_surface_snapshot_copy_on_write (cairo_surface_t *surface) { cairo_surface_snapshot_t *snapshot = (cairo_surface_snapshot_t *) surface; cairo_image_surface_t *image; cairo_image_surface_t *clone; void *extra; cairo_status_t status; /* We need to make an image copy of the original surface since the * snapshot may exceed the lifetime of the original device, i.e. * when we later need to use the snapshot the data may have already * been lost. */ status = _cairo_surface_acquire_source_image (snapshot->target, &image, &extra); if (unlikely (status)) { snapshot->target = _cairo_surface_create_in_error (status); status = _cairo_surface_set_error (surface, status); return; } clone = (cairo_image_surface_t *) _cairo_image_surface_create_with_pixman_format (NULL, image->pixman_format, image->width, image->height, 0); if (likely (clone->base.status == CAIRO_STATUS_SUCCESS)) { if (clone->stride == image->stride) { memcpy (clone->data, image->data, image->stride * image->height); } else { pixman_image_composite32 (PIXMAN_OP_SRC, image->pixman_image, NULL, clone->pixman_image, 0, 0, 0, 0, 0, 0, image->width, image->height); } clone->base.is_clear = FALSE; snapshot->clone = &clone->base; } else { snapshot->clone = &clone->base; status = _cairo_surface_set_error (surface, clone->base.status); } _cairo_surface_release_source_image (snapshot->target, image, extra); snapshot->target = snapshot->clone; snapshot->base.type = snapshot->target->type; }
static void _cairo_xcb_surface_release_source_image (void *abstract_surface, cairo_image_surface_t *image, void *image_extra) { cairo_xcb_surface_t *surface = abstract_surface; if (surface->drm != NULL && ! surface->marked_dirty) { return _cairo_surface_release_source_image (surface->drm, image, image_extra); } cairo_surface_destroy (&image->base); }
static cairo_int_status_t _cairo_skia_surface_fill (void *asurface, cairo_operator_t op, const cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, cairo_clip_t *clip) { cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface; cairo_image_surface_t *image = NULL; cairo_status_t status; void *image_extra; status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); if (unlikely (status)) return (cairo_int_status_t) status; SkPaint paint; paint.setStyle (SkPaint::kFill_Style); SkColor color; if (pattern_to_sk_color (source, color)) { paint.setColor (color); } else { SkShader *shader = pattern_to_sk_shader (surface, source, &image, &image_extra); if (shader == NULL) return UNSUPPORTED("pattern to shader conversion"); paint.setShader (shader); shader->unref (); paint.setFilterBitmap (pattern_filter_to_sk (source)); } paint.setXfermodeMode (operator_to_sk (op)); paint.setAntiAlias (antialias != CAIRO_ANTIALIAS_NONE); surface->canvas->drawPath (path_to_sk (path, fill_rule), paint); if (image != NULL) { _cairo_surface_release_source_image (&surface->base, image, image_extra); } return CAIRO_INT_STATUS_SUCCESS; }
static void _cairo_surface_snapshot_copy_on_write (cairo_surface_t *surface) { cairo_surface_snapshot_t *snapshot = (cairo_surface_snapshot_t *) surface; cairo_image_surface_t *image; cairo_surface_t *clone; void *extra; cairo_status_t status; TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, snapshot->target->unique_id)); /* We need to make an image copy of the original surface since the * snapshot may exceed the lifetime of the original device, i.e. * when we later need to use the snapshot the data may have already * been lost. */ CAIRO_MUTEX_LOCK (snapshot->mutex); if (snapshot->target->backend->snapshot != NULL) { clone = snapshot->target->backend->snapshot (snapshot->target); if (clone != NULL) { assert (clone->status || ! _cairo_surface_is_snapshot (clone)); goto done; } } /* XXX copy to a similar surface, leave acquisition till later? * We should probably leave such decisions to the backend in case we * rely upon devices/connections like Xlib. */ status = _cairo_surface_acquire_source_image (snapshot->target, &image, &extra); if (unlikely (status)) { snapshot->target = _cairo_surface_create_in_error (status); status = _cairo_surface_set_error (surface, status); goto unlock; } clone = image->base.backend->snapshot (&image->base); _cairo_surface_release_source_image (snapshot->target, image, extra); done: status = _cairo_surface_set_error (surface, clone->status); snapshot->target = snapshot->clone = clone; snapshot->base.type = clone->type; unlock: CAIRO_MUTEX_UNLOCK (snapshot->mutex); }
static cairo_int_status_t _cairo_skia_surface_stroke (void *asurface, cairo_operator_t op, const cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_stroke_style_t *style, cairo_matrix_t *ctm, cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, cairo_clip_t *clip) { cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface; cairo_image_surface_t *image = NULL; cairo_status_t status; void *image_extra; status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); if (unlikely (status)) return (cairo_int_status_t) status; SkPaint paint; paint.setStyle (SkPaint::kStroke_Style); SkColor color; if (pattern_to_sk_color (source, color)) { paint.setColor (color); } else { SkShader *shader = pattern_to_sk_shader (surface, source, &image, &image_extra); if (shader == NULL) return UNSUPPORTED("pattern to shader conversion"); paint.setShader (shader); shader->unref (); paint.setFilterBitmap (pattern_filter_to_sk (source)); } paint.setXfermodeMode (operator_to_sk (op)); paint.setAntiAlias (antialias != CAIRO_ANTIALIAS_NONE); /* Convert the various stroke rendering bits */ paint.setStrokeWidth (SkFloatToScalar (style->line_width)); paint.setStrokeMiter (SkFloatToScalar (style->miter_limit)); static const SkPaint::Cap capMap[] = { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap }; paint.setStrokeCap (capMap[style->line_cap]); static const SkPaint::Join joinMap[] = { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join }; paint.setStrokeJoin (joinMap[style->line_join]); /* If we have a dash pattern, we need to * create a SkDashPathEffect and set it on the Paint. */ if (style->dash != NULL) { SkScalar intervals_static[20]; SkScalar *intervals = intervals_static; int loop = 0; unsigned int dash_count = style->num_dashes; if ((dash_count & 1) != 0) { loop = 1; dash_count <<= 1; } if (dash_count > 20) intervals = new SkScalar[dash_count]; unsigned int i = 0; do { for (unsigned int j = 0; i < style->num_dashes; j++) intervals[i++] = SkFloatToScalar (style->dash[j]); } while (loop--); SkDashPathEffect *dash = new SkDashPathEffect (intervals, dash_count, SkFloatToScalar (style->dash_offset)); paint.setPathEffect (dash); dash->unref (); } surface->canvas->save (SkCanvas::kMatrix_SaveFlag); surface->canvas->concat (matrix_to_sk (*ctm)); surface->canvas->drawPath (path_to_sk (path, ctm_inverse), paint); surface->canvas->restore (); if (image != NULL) { _cairo_surface_release_source_image (&surface->base, image, image_extra); } return CAIRO_INT_STATUS_SUCCESS; }
~PatternToBrushConverter () { if (mAcquiredImageParent) _cairo_surface_release_source_image (mAcquiredImageParent, mAcquiredImage, mAcquiredImageExtra); }
static cairo_status_t upload_boxes (cairo_win32_display_surface_t *dst, const cairo_pattern_t *source, cairo_boxes_t *boxes) { const cairo_surface_pattern_t *pattern; struct upload_box cb; cairo_surface_t *surface; cairo_image_surface_t *image; void *image_extra; cairo_status_t status; TRACE ((stderr, "%s\n", __FUNCTION__)); if ((dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB) == 0) return CAIRO_INT_STATUS_UNSUPPORTED; if (! _cairo_matrix_is_integer_translation (&source->matrix, &cb.tx, &cb.ty)) return CAIRO_INT_STATUS_UNSUPPORTED; pattern = (const cairo_surface_pattern_t *) source; surface = _cairo_surface_get_source (pattern->surface, &cb.limit); /* First check that the data is entirely within the image */ if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb)) return CAIRO_INT_STATUS_UNSUPPORTED; if (surface->type != CAIRO_SURFACE_TYPE_IMAGE) { status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); if (status) return status; } else image = to_image_surface(surface); status = CAIRO_INT_STATUS_UNSUPPORTED; if (!(image->format == CAIRO_FORMAT_ARGB32 || image->format == CAIRO_FORMAT_RGB24)) goto err; if (image->stride != 4*image->width) goto err; cb.dst = dst->win32.dc; cb.data = image->data; cb.bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); cb.bi.bmiHeader.biWidth = image->width; cb.bi.bmiHeader.biHeight = -image->height; cb.bi.bmiHeader.biSizeImage = 0; cb.bi.bmiHeader.biXPelsPerMeter = PELS_72DPI; cb.bi.bmiHeader.biYPelsPerMeter = PELS_72DPI; cb.bi.bmiHeader.biPlanes = 1; cb.bi.bmiHeader.biBitCount = 32; cb.bi.bmiHeader.biCompression = BI_RGB; cb.bi.bmiHeader.biClrUsed = 0; cb.bi.bmiHeader.biClrImportant = 0; cb.tx += cb.limit.x; cb.ty += cb.limit.y; status = CAIRO_STATUS_SUCCESS; if (! _cairo_boxes_for_each_box (boxes, upload_box, &cb)) status = CAIRO_INT_STATUS_UNSUPPORTED; _cairo_win32_display_surface_discard_fallback (dst); err: if (&image->base != surface) _cairo_surface_release_source_image (surface, image, image_extra); return status; }