Getting rid of GetDefaultProfile(), clean up of ProfileManager (which was in a seriou...
[chromium-blink-merge.git] / skia / ext / bitmap_platform_device_cairo.cc
blob3619eb252771e9f80e2c2f02756047adad44593f
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "skia/ext/bitmap_platform_device_cairo.h"
6 #include "skia/ext/platform_canvas.h"
8 #if defined(OS_OPENBSD)
9 #include <cairo.h>
10 #else
11 #include <cairo/cairo.h>
12 #endif
14 namespace skia {
16 namespace {
18 // CairoSurfacePixelRef is an SkPixelRef that is backed by a cairo surface.
19 class SK_API CairoSurfacePixelRef : public SkPixelRef {
20 public:
21 // The constructor takes ownership of the passed-in surface.
22 explicit CairoSurfacePixelRef(const SkImageInfo& info,
23 cairo_surface_t* surface);
24 virtual ~CairoSurfacePixelRef();
26 SK_DECLARE_UNFLATTENABLE_OBJECT();
28 protected:
29 virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
30 virtual void onUnlockPixels() SK_OVERRIDE;
32 private:
33 cairo_surface_t* surface_;
36 CairoSurfacePixelRef::CairoSurfacePixelRef(const SkImageInfo& info,
37 cairo_surface_t* surface)
38 : SkPixelRef(info), surface_(surface) {
41 CairoSurfacePixelRef::~CairoSurfacePixelRef() {
42 if (surface_)
43 cairo_surface_destroy(surface_);
46 void* CairoSurfacePixelRef::onLockPixels(SkColorTable** color_table) {
47 *color_table = NULL;
48 return cairo_image_surface_get_data(surface_);
51 void CairoSurfacePixelRef::onUnlockPixels() {
52 // Nothing to do.
53 return;
56 void LoadMatrixToContext(cairo_t* context, const SkMatrix& matrix) {
57 cairo_matrix_t cairo_matrix;
58 cairo_matrix_init(&cairo_matrix,
59 SkScalarToFloat(matrix.getScaleX()),
60 SkScalarToFloat(matrix.getSkewY()),
61 SkScalarToFloat(matrix.getSkewX()),
62 SkScalarToFloat(matrix.getScaleY()),
63 SkScalarToFloat(matrix.getTranslateX()),
64 SkScalarToFloat(matrix.getTranslateY()));
65 cairo_set_matrix(context, &cairo_matrix);
68 void LoadClipToContext(cairo_t* context, const SkRegion& clip) {
69 cairo_reset_clip(context);
71 // TODO(brettw) support non-rect clips.
72 SkIRect bounding = clip.getBounds();
73 cairo_rectangle(context, bounding.fLeft, bounding.fTop,
74 bounding.fRight - bounding.fLeft,
75 bounding.fBottom - bounding.fTop);
76 cairo_clip(context);
79 } // namespace
81 void BitmapPlatformDevice::SetMatrixClip(
82 const SkMatrix& transform,
83 const SkRegion& region) {
84 transform_ = transform;
85 clip_region_ = region;
86 config_dirty_ = true;
89 void BitmapPlatformDevice::LoadConfig() {
90 if (!config_dirty_ || !cairo_)
91 return; // Nothing to do.
92 config_dirty_ = false;
94 // Load the identity matrix since this is what our clip is relative to.
95 cairo_matrix_t cairo_matrix;
96 cairo_matrix_init_identity(&cairo_matrix);
97 cairo_set_matrix(cairo_, &cairo_matrix);
99 LoadClipToContext(cairo_, clip_region_);
100 LoadMatrixToContext(cairo_, transform_);
103 // We use this static factory function instead of the regular constructor so
104 // that we can create the pixel data before calling the constructor. This is
105 // required so that we can call the base class' constructor with the pixel
106 // data.
107 BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
108 bool is_opaque,
109 cairo_surface_t* surface) {
110 if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
111 cairo_surface_destroy(surface);
112 return NULL;
115 SkImageInfo info = {
116 width,
117 height,
118 kPMColor_SkColorType,
119 is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType
122 SkBitmap bitmap;
123 bitmap.setConfig(info, cairo_image_surface_get_stride(surface));
124 RefPtr<SkPixelRef> pixel_ref = AdoptRef(new CairoSurfacePixelRef(info,
125 surface));
126 bitmap.setPixelRef(pixel_ref.get());
128 // The device object will take ownership of the graphics context.
129 return new BitmapPlatformDevice(bitmap, surface);
132 BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
133 bool is_opaque) {
134 // This initializes the bitmap to all zeros.
135 cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
136 width, height);
138 BitmapPlatformDevice* device = Create(width, height, is_opaque, surface);
140 #ifndef NDEBUG
141 if (device && is_opaque) // Fill with bright bluish green
142 device->eraseColor(SkColorSetARGB(255, 0, 255, 128));
143 #endif
145 return device;
148 BitmapPlatformDevice* BitmapPlatformDevice::CreateAndClear(int width,
149 int height,
150 bool is_opaque) {
151 // The Linux port always constructs initialized bitmaps, so there is no extra
152 // work to perform here.
153 return Create(width, height, is_opaque);
156 BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
157 bool is_opaque,
158 uint8_t* data) {
159 cairo_surface_t* surface = cairo_image_surface_create_for_data(
160 data, CAIRO_FORMAT_ARGB32, width, height,
161 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));
163 return Create(width, height, is_opaque, surface);
166 // The device will own the bitmap, which corresponds to also owning the pixel
167 // data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap.
168 BitmapPlatformDevice::BitmapPlatformDevice(
169 const SkBitmap& bitmap,
170 cairo_surface_t* surface)
171 : SkBitmapDevice(bitmap),
172 cairo_(cairo_create(surface)),
173 config_dirty_(true),
174 transform_(SkMatrix::I()) { // Want to load the config next time.
175 SetPlatformDevice(this, this);
178 BitmapPlatformDevice::~BitmapPlatformDevice() {
179 cairo_destroy(cairo_);
182 SkBaseDevice* BitmapPlatformDevice::onCreateCompatibleDevice(
183 SkBitmap::Config config, int width, int height, bool isOpaque,
184 Usage /*usage*/) {
185 SkASSERT(config == SkBitmap::kARGB_8888_Config);
186 return BitmapPlatformDevice::Create(width, height, isOpaque);
189 cairo_t* BitmapPlatformDevice::BeginPlatformPaint() {
190 LoadConfig();
191 cairo_surface_t* surface = cairo_get_target(cairo_);
192 // Tell cairo to flush anything it has pending.
193 cairo_surface_flush(surface);
194 // Tell Cairo that we (probably) modified (actually, will modify) its pixel
195 // buffer directly.
196 cairo_surface_mark_dirty(surface);
197 return cairo_;
200 void BitmapPlatformDevice::DrawToNativeContext(
201 PlatformSurface surface, int x, int y, const PlatformRect* src_rect) {
202 // Should never be called on Linux.
203 SkASSERT(false);
206 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
207 const SkRegion& region,
208 const SkClipStack&) {
209 SetMatrixClip(transform, region);
212 // PlatformCanvas impl
214 SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque,
215 uint8_t* data, OnFailureType failureType) {
216 skia::RefPtr<SkBaseDevice> dev = skia::AdoptRef(
217 BitmapPlatformDevice::Create(width, height, is_opaque, data));
218 return CreateCanvas(dev, failureType);
221 // Port of PlatformBitmap to linux
222 PlatformBitmap::~PlatformBitmap() {
223 cairo_destroy(surface_);
226 bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
227 SkImageInfo info = {
228 width,
229 height,
230 kPMColor_SkColorType,
231 is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType
234 // The SkBitmap allocates and owns the bitmap memory; PlatformBitmap owns the
235 // cairo drawing context tied to the bitmap. The SkBitmap's pixelRef can
236 // outlive the PlatformBitmap if additional copies are made.
237 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
238 bitmap_.setConfig(info, stride);
240 cairo_surface_t* surf = cairo_image_surface_create(
241 CAIRO_FORMAT_ARGB32,
242 width,
243 height);
244 if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) {
245 cairo_surface_destroy(surf);
246 return false;
248 RefPtr<SkPixelRef> pixel_ref = AdoptRef(new CairoSurfacePixelRef(info, surf));
249 bitmap_.setPixelRef(pixel_ref.get());
250 return true;
253 } // namespace skia