| Index: skia/ext/layer_allocator_cairo.cc
|
| diff --git a/skia/ext/layer_allocator_cairo.cc b/skia/ext/layer_allocator_cairo.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7519f5bebe9cb82ed722b1b9f34e0bb6cf027ef4
|
| --- /dev/null
|
| +++ b/skia/ext/layer_allocator_cairo.cc
|
| @@ -0,0 +1,112 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "build/build_config.h"
|
| +#include "skia/ext/layer_allocator_cairo.h"
|
| +#include "third_party/skia/include/core/SkMatrix.h"
|
| +#include "third_party/skia/include/core/SkRect.h"
|
| +
|
| +#if defined(OS_OPENBSD)
|
| +#include <cairo.h>
|
| +#else
|
| +#include <cairo/cairo.h>
|
| +#endif
|
| +
|
| +typedef struct _cairo_surface cairo_surface_t;
|
| +
|
| +namespace {
|
| +
|
| +void LoadMatrixToContext(cairo_t* context, const SkMatrix& matrix) {
|
| + cairo_matrix_t cairo_matrix;
|
| + cairo_matrix_init(&cairo_matrix,
|
| + SkScalarToFloat(matrix.getScaleX()),
|
| + SkScalarToFloat(matrix.getSkewY()),
|
| + SkScalarToFloat(matrix.getSkewX()),
|
| + SkScalarToFloat(matrix.getScaleY()),
|
| + SkScalarToFloat(matrix.getTranslateX()),
|
| + SkScalarToFloat(matrix.getTranslateY()));
|
| + cairo_set_matrix(context, &cairo_matrix);
|
| +}
|
| +
|
| +void LoadClipToContext(cairo_t* context, const SkIRect& clip_bounds) {
|
| + cairo_reset_clip(context);
|
| +
|
| + cairo_rectangle(context, clip_bounds.fLeft, clip_bounds.fTop,
|
| + clip_bounds.width(), clip_bounds.height());
|
| + cairo_clip(context);
|
| +}
|
| +
|
| +void FreeCairoBacking(void* context) {
|
| + if (!context)
|
| + return;
|
| + cairo_surface_destroy(cairo_get_target((cairo_t*) context));
|
| + cairo_destroy((cairo_t*) context);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace skia {
|
| +
|
| +LayerAllocator::LayerAllocator() { }
|
| +
|
| +LayerAllocator::~LayerAllocator() { }
|
| +
|
| +void* LayerAllocator::getNativeContext(void* buffer,
|
| + const SkMatrix& transform,
|
| + const SkIRect& clip_bounds) {
|
| + if (!buffer)
|
| + return nullptr;
|
| +
|
| + context_map_t::iterator context_iterator = contexts_.find(buffer);
|
| + if (context_iterator == contexts_.end())
|
| + return nullptr;
|
| +
|
| + LoadClipToContext(context_iterator->second, clip_bounds);
|
| + LoadMatrixToContext(context_iterator->second, transform);
|
| + cairo_surface_t* surface = cairo_get_target(context_iterator->second);
|
| + cairo_surface_flush(surface);
|
| + cairo_surface_mark_dirty(surface);
|
| + return context_iterator->second;
|
| +}
|
| +
|
| +void* LayerAllocator::allocateLayer(const SkImageInfo& info,
|
| + size_t* rowBytes,
|
| + void (**deallocator)(void*),
|
| + void** deallocatorPayload,
|
| + void* initialData) {
|
| + SkASSERT(info.colorType() == kN32_SkColorType);
|
| +
|
| + cairo_surface_t* surface;
|
| + if (initialData)
|
| + surface = cairo_image_surface_create_for_data(
|
| + (unsigned char*) initialData,
|
| + CAIRO_FORMAT_ARGB32,
|
| + info.width(),
|
| + info.height(),
|
| + cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, info.width()));
|
| + else
|
| + surface = cairo_image_surface_create(
|
| + CAIRO_FORMAT_ARGB32, info.width(), info.height());
|
| + if (!surface)
|
| + return nullptr;
|
| +
|
| + if (rowBytes)
|
| + *rowBytes = cairo_image_surface_get_stride(surface);
|
| +
|
| + cairo_t* context = cairo_create(surface);
|
| + if (!context) {
|
| + cairo_surface_destroy(surface);
|
| + return nullptr;
|
| + }
|
| + void* buffer = cairo_image_surface_get_data(surface);
|
| + contexts_.insert({buffer, context});
|
| +
|
| + *deallocator = FreeCairoBacking;
|
| + *deallocatorPayload = context;
|
| +
|
| + return buffer;
|
| +}
|
| +
|
| +} // namespace skia
|
| +
|
|
|