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 |
+ |