1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "skia/ext/bitmap_platform_device_cairo.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/platform_canvas.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_OPENBSD)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cairo.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cairo/cairo.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace skia {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CairoSurfaceReleaseProc(void*, void* context) {
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SkASSERT(context);
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cairo_surface_destroy(static_cast<cairo_surface_t*>(context));
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Back the destination bitmap by a Cairo surface.  The bitmap's
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// pixelRef takes ownership of the passed-in surface and will call
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// cairo_surface_destroy() upon destruction.
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Note: it may immediately destroy the surface, if it fails to create a bitmap
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// with pixels, thus the caller must either ref() the surface before hand, or
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// it must not refer to the surface after this call.
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool InstallCairoSurfacePixels(SkBitmap* dst,
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               cairo_surface_t* surface,
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               bool is_opaque) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SkASSERT(dst);
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!surface) {
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SkImageInfo info
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      = SkImageInfo::MakeN32Premul(cairo_image_surface_get_width(surface),
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   cairo_image_surface_get_height(surface));
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return dst->installPixels(info,
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            cairo_image_surface_get_data(surface),
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            cairo_image_surface_get_stride(surface),
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            NULL,
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            &CairoSurfaceReleaseProc,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            static_cast<void*>(surface));
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LoadMatrixToContext(cairo_t* context, const SkMatrix& matrix) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_matrix_t cairo_matrix;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_matrix_init(&cairo_matrix,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    SkScalarToFloat(matrix.getScaleX()),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    SkScalarToFloat(matrix.getSkewY()),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    SkScalarToFloat(matrix.getSkewX()),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    SkScalarToFloat(matrix.getScaleY()),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    SkScalarToFloat(matrix.getTranslateX()),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    SkScalarToFloat(matrix.getTranslateY()));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_set_matrix(context, &cairo_matrix);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LoadClipToContext(cairo_t* context, const SkRegion& clip) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_reset_clip(context);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(brettw) support non-rect clips.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkIRect bounding = clip.getBounds();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_rectangle(context, bounding.fLeft, bounding.fTop,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  bounding.fRight - bounding.fLeft,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  bounding.fBottom - bounding.fTop);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_clip(context);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BitmapPlatformDevice::SetMatrixClip(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SkMatrix& transform,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SkRegion& region) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform_ = transform;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clip_region_ = region;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_dirty_ = true;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BitmapPlatformDevice::LoadConfig() {
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!config_dirty_ || !cairo_)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Nothing to do.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_dirty_ = false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load the identity matrix since this is what our clip is relative to.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_matrix_t cairo_matrix;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_matrix_init_identity(&cairo_matrix);
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  cairo_set_matrix(cairo_, &cairo_matrix);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LoadClipToContext(cairo_, clip_region_);
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LoadMatrixToContext(cairo_, transform_);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use this static factory function instead of the regular constructor so
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that we can create the pixel data before calling the constructor. This is
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// required so that we can call the base class' constructor with the pixel
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   bool is_opaque,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   cairo_surface_t* surface) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_surface_destroy(surface);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // must call this before trying to install the surface, since that may result
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // in the surface being destroyed.
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  cairo_t* cairo = cairo_create(surface);
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap bitmap;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!InstallCairoSurfacePixels(&bitmap, surface, is_opaque)) {
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    cairo_destroy(cairo);
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The device object will take ownership of the graphics context.
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return new BitmapPlatformDevice(bitmap, cairo);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   bool is_opaque) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This initializes the bitmap to all zeros.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                        width, height);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BitmapPlatformDevice* device = Create(width, height, is_opaque, surface);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (device && is_opaque)  // Fill with bright bluish green
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->eraseColor(SkColorSetARGB(255, 0, 255, 128));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return device;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BitmapPlatformDevice* BitmapPlatformDevice::CreateAndClear(int width,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           int height,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           bool is_opaque) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The Linux port always constructs initialized bitmaps, so there is no extra
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // work to perform here.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Create(width, height, is_opaque);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   bool is_opaque,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   uint8_t* data) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_surface_t* surface = cairo_image_surface_create_for_data(
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data, CAIRO_FORMAT_ARGB32, width, height,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Create(width, height, is_opaque, surface);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Ownership of the cairo object is transferred.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BitmapPlatformDevice::BitmapPlatformDevice(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SkBitmap& bitmap,
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    cairo_t* cairo)
159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : SkBitmapDevice(bitmap),
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      cairo_(cairo),
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      config_dirty_(true),
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      transform_(SkMatrix::I()) {  // Want to load the config next time.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetPlatformDevice(this, this);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BitmapPlatformDevice::~BitmapPlatformDevice() {
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  cairo_destroy(cairo_);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const SkImageInfo& info,
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                   Usage /*usage*/) {
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SkASSERT(info.colorType() == kN32_SkColorType);
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return BitmapPlatformDevice::Create(info.width(), info.height(),
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      info.isOpaque());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cairo_t* BitmapPlatformDevice::BeginPlatformPaint() {
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LoadConfig();
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  cairo_surface_t* surface = cairo_get_target(cairo_);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell cairo to flush anything it has pending.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_surface_flush(surface);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell Cairo that we (probably) modified (actually, will modify) its pixel
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // buffer directly.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_surface_mark_dirty(surface);
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return cairo_;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BitmapPlatformDevice::DrawToNativeContext(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlatformSurface surface, int x, int y, const PlatformRect* src_rect) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should never be called on Linux.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(false);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkRegion& region,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkClipStack&) {
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetMatrixClip(transform, region);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// PlatformCanvas impl
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               uint8_t* data, OnFailureType failureType) {
204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  skia::RefPtr<SkBaseDevice> dev = skia::AdoptRef(
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BitmapPlatformDevice::Create(width, height, is_opaque, data));
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return CreateCanvas(dev, failureType);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Port of PlatformBitmap to linux
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PlatformBitmap::~PlatformBitmap() {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_destroy(surface_);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The SkBitmap allocates and owns the bitmap memory; PlatformBitmap owns the
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // cairo drawing context tied to the bitmap. The SkBitmap's pixelRef can
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // outlive the PlatformBitmap if additional copies are made.
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  cairo_surface_t* surf = cairo_image_surface_create(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CAIRO_FORMAT_ARGB32,
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      width,
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      height);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_surface_destroy(surf);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return InstallCairoSurfacePixels(&bitmap_, surf, is_opaque);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace skia
232