Commit 0f9a1371 authored by sky's avatar sky Committed by Commit bot

Revert of Delete Mac & Cairo skia::BitmapPlatformDevice impls (patchset #3...

Revert of Delete Mac & Cairo skia::BitmapPlatformDevice impls (patchset #3 id:40001 of https://codereview.chromium.org/2611153002/ )

Reason for revert:
Revert in hopes of fix linux x64 bot: https://build.chromium.org/p/chromium.chrome/builders/Google%20Chrome%20Linux%20x64/builds/15545

Original issue's description:
> Delete Mac & Cairo skia::BitmapPlatformDevice impls
>
> We are no longer performing native drawing on these platforms, use the
> Skia placeholder instead.
>
> BUG=675977
> R=reed@google.com
> TBR=
>
> Review-Url: https://codereview.chromium.org/2611153002
> Cr-Commit-Position: refs/heads/master@{#441750}
> Committed: https://chromium.googlesource.com/chromium/src/+/ccdceaed36d07ad5ab6d5e504ece0459a4aeaddf

TBR=reed@google.com,robertphillips@chromium.org,fmalita@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=675977

Review-Url: https://codereview.chromium.org/2616003003
Cr-Commit-Position: refs/heads/master@{#441776}
parent 495d8354
...@@ -367,6 +367,10 @@ component("skia") { ...@@ -367,6 +367,10 @@ component("skia") {
# Select the right BitmapPlatformDevice. # Select the right BitmapPlatformDevice.
if (is_win) { if (is_win) {
sources += [ "ext/bitmap_platform_device_win.cc" ] sources += [ "ext/bitmap_platform_device_win.cc" ]
} else if (is_mac) {
sources += [ "ext/bitmap_platform_device_mac.cc" ]
} else if (use_cairo) {
sources += [ "ext/bitmap_platform_device_cairo.cc" ]
} else if (!is_ios) { } else if (!is_ios) {
sources += [ "ext/bitmap_platform_device_skia.cc" ] sources += [ "ext/bitmap_platform_device_skia.cc" ]
} }
......
// Copyright (c) 2012 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.
#ifndef SKIA_EXT_BITMAP_PLATFORM_DEVICE_H_
#define SKIA_EXT_BITMAP_PLATFORM_DEVICE_H_
// This file provides an easy way to include the appropriate
// BitmapPlatformDevice header file for your platform.
#include <stdint.h>
#if defined(WIN32)
#include "skia/ext/bitmap_platform_device_win.h"
#elif defined(__APPLE__)
#include "skia/ext/bitmap_platform_device_mac.h"
#elif defined(USE_CAIRO)
#include "skia/ext/bitmap_platform_device_cairo.h"
#else
#include "skia/ext/bitmap_platform_device_skia.h"
#endif
#endif // SKIA_EXT_BITMAP_PLATFORM_DEVICE_H_
// Copyright 2013 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/bitmap_platform_device_cairo.h"
#include "skia/ext/platform_canvas.h"
#if defined(OS_OPENBSD)
#include <cairo.h>
#else
#include <cairo/cairo.h>
#endif
namespace skia {
namespace {
void CairoSurfaceReleaseProc(void*, void* context) {
SkASSERT(context);
cairo_surface_destroy(static_cast<cairo_surface_t*>(context));
}
// Back the destination bitmap by a Cairo surface. The bitmap's
// pixelRef takes ownership of the passed-in surface and will call
// cairo_surface_destroy() upon destruction.
//
// Note: it may immediately destroy the surface, if it fails to create a bitmap
// with pixels, thus the caller must either ref() the surface before hand, or
// it must not refer to the surface after this call.
bool InstallCairoSurfacePixels(SkBitmap* dst,
cairo_surface_t* surface,
bool is_opaque) {
SkASSERT(dst);
if (!surface) {
return false;
}
SkImageInfo info
= SkImageInfo::MakeN32(cairo_image_surface_get_width(surface),
cairo_image_surface_get_height(surface),
is_opaque ? kOpaque_SkAlphaType
: kPremul_SkAlphaType);
return dst->installPixels(info,
cairo_image_surface_get_data(surface),
cairo_image_surface_get_stride(surface),
NULL,
&CairoSurfaceReleaseProc,
static_cast<void*>(surface));
}
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);
}
} // namespace
void BitmapPlatformDevice::LoadConfig(const SkMatrix& transform,
const SkIRect& clip_bounds) {
if (!cairo_)
return; // Nothing to do.
LoadClipToContext(cairo_, clip_bounds);
LoadMatrixToContext(cairo_, transform);
}
// We use this static factory function instead of the regular constructor so
// that we can create the pixel data before calling the constructor. This is
// required so that we can call the base class' constructor with the pixel
// data.
BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
bool is_opaque,
cairo_surface_t* surface) {
if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy(surface);
return NULL;
}
// must call this before trying to install the surface, since that may result
// in the surface being destroyed.
cairo_t* cairo = cairo_create(surface);
SkBitmap bitmap;
if (!InstallCairoSurfacePixels(&bitmap, surface, is_opaque)) {
cairo_destroy(cairo);
return NULL;
}
// The device object will take ownership of the graphics context.
return new BitmapPlatformDevice(bitmap, cairo);
}
BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
bool is_opaque) {
// This initializes the bitmap to all zeros.
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
width, height);
BitmapPlatformDevice* device = Create(width, height, is_opaque, surface);
#ifndef NDEBUG
if (device && is_opaque) // Fill with bright bluish green
SkCanvas(device).drawColor(0xFF00FF80);
#endif
return device;
}
BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
bool is_opaque,
uint8_t* data) {
cairo_surface_t* surface = cairo_image_surface_create_for_data(
data, CAIRO_FORMAT_ARGB32, width, height,
cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));
return Create(width, height, is_opaque, surface);
}
// Ownership of the cairo object is transferred.
BitmapPlatformDevice::BitmapPlatformDevice(
const SkBitmap& bitmap,
cairo_t* cairo)
: SkBitmapDevice(bitmap),
cairo_(cairo) {
SetPlatformDevice(this, this);
}
BitmapPlatformDevice::~BitmapPlatformDevice() {
cairo_destroy(cairo_);
}
SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& info,
const SkPaint*) {
SkASSERT(info.fInfo.colorType() == kN32_SkColorType);
return BitmapPlatformDevice::Create(info.fInfo.width(), info.fInfo.height(),
info.fInfo.isOpaque());
}
cairo_t* BitmapPlatformDevice::BeginPlatformPaint(
const SkMatrix& transform,
const SkIRect& clip_bounds) {
LoadConfig(transform, clip_bounds);
cairo_surface_t* surface = cairo_get_target(cairo_);
// Tell cairo to flush anything it has pending.
cairo_surface_flush(surface);
// Tell Cairo that we (probably) modified (actually, will modify) its pixel
// buffer directly.
cairo_surface_mark_dirty(surface);
return cairo_;
}
// PlatformCanvas impl
std::unique_ptr<SkCanvas> CreatePlatformCanvasWithPixels(
int width,
int height,
bool is_opaque,
uint8_t* data,
OnFailureType failureType) {
sk_sp<SkBaseDevice> dev(
BitmapPlatformDevice::Create(width, height, is_opaque, data));
return CreateCanvas(dev, failureType);
}
} // namespace skia
// Copyright 2013 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.
#ifndef SKIA_EXT_BITMAP_PLATFORM_DEVICE_CAIRO_H_
#define SKIA_EXT_BITMAP_PLATFORM_DEVICE_CAIRO_H_
#include <stdint.h>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "skia/ext/platform_device.h"
typedef struct _cairo_surface cairo_surface_t;
// -----------------------------------------------------------------------------
// Image byte ordering on Linux:
//
// Pixels are packed into 32-bit words these days. Even for 24-bit images,
// often 8-bits will be left unused for alignment reasons. Thus, when you see
// ARGB as the byte order you have to wonder if that's in memory order or
// little-endian order. Here I'll write A.R.G.B to specifiy the memory order.
//
// GdkPixbuf's provide a nice backing store and defaults to R.G.B.A order.
// They'll do the needed byte swapping to match the X server when drawn.
//
// Skia can be controled in skia/include/corecg/SkUserConfig.h (see bits about
// SK_R32_SHIFT). For Linux we define it to be ARGB in registers. For little
// endian machines that means B.G.R.A in memory.
//
// The image loaders are controlled in
// webkit/port/platform/image-decoders/ImageDecoder.h (see setRGBA). These are
// also configured for ARGB in registers.
//
// Cairo's only 32-bit mode is ARGB in registers.
//
// X servers commonly have a 32-bit visual with xRGB in registers (since they
// typically don't do alpha blending of drawables at the user level. Composite
// extensions aside.)
//
// We don't use GdkPixbuf because its byte order differs from the rest. Most
// importantly, it differs from Cairo which, being a system library, is
// something that we can't easily change.
// -----------------------------------------------------------------------------
namespace skia {
// -----------------------------------------------------------------------------
// This is the Linux bitmap backing for Skia. We create a Cairo image surface
// to store the backing buffer. This buffer is BGRA in memory (on little-endian
// machines).
//
// For now we are also using Cairo to paint to the Drawables so we provide an
// accessor for getting the surface.
//
// This is all quite ok for test_shell. In the future we will want to use
// shared memory between the renderer and the main process at least. In this
// case we'll probably create the buffer from a precreated region of memory.
// -----------------------------------------------------------------------------
class BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
public:
// Create a BitmapPlatformDeviceLinux from an already constructed bitmap;
// you should probably be using Create(). This may become private later if
// we ever have to share state between some native drawing UI and Skia, like
// the Windows and Mac versions of this class do.
//
// This object takes ownership of @cairo.
BitmapPlatformDevice(const SkBitmap& other, cairo_t* cairo);
~BitmapPlatformDevice() override;
// Constructs a device with size |width| * |height| with contents initialized
// to zero. |is_opaque| should be set if the caller knows the bitmap will be
// completely opaque and allows some optimizations.
static BitmapPlatformDevice* Create(int width, int height, bool is_opaque);
// This doesn't take ownership of |data|. If |data| is NULL, the contents
// of the device are initialized to 0.
static BitmapPlatformDevice* Create(int width, int height, bool is_opaque,
uint8_t* data);
protected:
SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
private:
// Overridden from PlatformDevice:
cairo_t* BeginPlatformPaint(const SkMatrix& transform,
const SkIRect& clip_bounds) override;
static BitmapPlatformDevice* Create(int width, int height, bool is_opaque,
cairo_surface_t* surface);
// Loads the current transform and clip into the context.
void LoadConfig(const SkMatrix& transform, const SkIRect& clip_bounds);
// Graphics context used to draw into the surface.
cairo_t* cairo_;
DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice);
};
} // namespace skia
#endif // SKIA_EXT_BITMAP_PLATFORM_DEVICE_CAIRO_H_
// Copyright (c) 2012 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 "skia/ext/bitmap_platform_device_mac.h"
#import <ApplicationServices/ApplicationServices.h>
#include <stddef.h>
#include <time.h>
#include "base/mac/mac_util.h"
#include "base/memory/ref_counted.h"
#include "skia/ext/bitmap_platform_device.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_mac.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkTypes.h"
namespace skia {
namespace {
// Returns true if it is unsafe to attempt to allocate an offscreen buffer
// given these dimensions.
bool RasterDeviceTooBigToAllocate(int width, int height) {
#ifndef SKIA_EXT_RASTER_DEVICE_ALLOCATION_MAX
#define SKIA_EXT_RASTER_DEVICE_ALLOCATION_MAX (2 * 256 * 1024 * 1024)
#endif
int bytesPerPixel = 4;
int64_t bytes = (int64_t)width * height * bytesPerPixel;
return bytes > SKIA_EXT_RASTER_DEVICE_ALLOCATION_MAX;
}
static CGContextRef CGContextForData(void* data, int width, int height) {
#define HAS_ARGB_SHIFTS(a, r, g, b) \
(SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \
&& SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b))
#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
// Allocate a bitmap context with 4 components per pixel (BGRA). Apple
// recommends these flags for improved CG performance.
// CGBitmapContextCreate returns NULL if width/height are 0. However, our
// callers expect to get a canvas back (which they later resize/reallocate)
// so we pin the dimensions here.
width = SkMax32(1, width);
height = SkMax32(1, height);
CGContextRef context =
CGBitmapContextCreate(data, width, height, 8, width * 4,
base::mac::GetSystemColorSpace(),
kCGImageAlphaPremultipliedFirst |
kCGBitmapByteOrder32Host);
#else
#error We require that Skia's and CoreGraphics's recommended \
image memory layout match.
#endif
#undef HAS_ARGB_SHIFTS
if (!context)
return NULL;
// Change the coordinate system to match WebCore's
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0, -1.0);
return context;
}
} // namespace
void BitmapPlatformDevice::ReleaseBitmapContext() {
SkASSERT(bitmap_context_);
CGContextRelease(bitmap_context_);
bitmap_context_ = NULL;
}
// Loads the specified Skia transform into the device context
static void LoadTransformToCGContext(CGContextRef context,
const SkMatrix& matrix) {
// CoreGraphics can concatenate transforms, but not reset the current one.
// So in order to get the required behavior here, we need to first make
// the current transformation matrix identity and only then load the new one.
// Reset matrix to identity.
CGAffineTransform orig_cg_matrix = CGContextGetCTM(context);
CGAffineTransform orig_cg_matrix_inv =
CGAffineTransformInvert(orig_cg_matrix);
CGContextConcatCTM(context, orig_cg_matrix_inv);
// assert that we have indeed returned to the identity Matrix.
SkASSERT(CGAffineTransformIsIdentity(CGContextGetCTM(context)));
// Convert xform to CG-land.
// Our coordinate system is flipped to match WebKit's so we need to modify
// the xform to match that.
SkMatrix transformed_matrix = matrix;
SkScalar sy = -matrix.getScaleY();
transformed_matrix.setScaleY(sy);
size_t height = CGBitmapContextGetHeight(context);
SkScalar ty = -matrix.getTranslateY(); // y axis is flipped.
transformed_matrix.setTranslateY(ty + (SkScalar)height);
CGAffineTransform cg_matrix =
skia::SkMatrixToCGAffineTransform(transformed_matrix);
// Load final transform into context.
CGContextConcatCTM(context, cg_matrix);
}
static void LoadClippingRegionToCGContext(CGContextRef context,
const SkIRect& clip_bounds,
const SkMatrix& transformation) {
// CoreGraphics applies the current transform to clip rects, which is
// unwanted. Inverse-transform the rect before sending it to CG. This only
// works for translations and scaling, but not for rotations (but the
// viewport is never rotated anyway).
SkMatrix t;
bool did_invert = transformation.invert(&t);
if (!did_invert)
t.reset();
SkRect rect = SkRect::Make(clip_bounds);
t.mapRect(&rect);
SkIRect irect;
rect.round(&irect);
CGContextClipToRect(context, skia::SkIRectToCGRect(irect));
}
void BitmapPlatformDevice::LoadConfig(const SkMatrix& transform,
const SkIRect& clip_bounds) {
if (!bitmap_context_)
return; // Nothing to do.
// We must restore and then save the state of the graphics context since the
// calls to Load the clipping region to the context are strictly cummulative,
// i.e., you can't replace a clip rect, other than with a save/restore.
// But this implies that no other changes to the state are done elsewhere.
// If we ever get to need to change this, then we must replace the clip rect
// calls in LoadClippingRegionToCGContext() with an image mask instead.
CGContextRestoreGState(bitmap_context_);
CGContextSaveGState(bitmap_context_);
LoadTransformToCGContext(bitmap_context_, transform);
LoadClippingRegionToCGContext(bitmap_context_, clip_bounds, transform);
}
// We use this static factory function instead of the regular constructor so
// that we can create the pixel data before calling the constructor. This is
// required so that we can call the base class' constructor with the pixel
// data.
BitmapPlatformDevice* BitmapPlatformDevice::Create(CGContextRef context,
int width,
int height,
bool is_opaque,
bool do_clear) {
if (RasterDeviceTooBigToAllocate(width, height))
return NULL;
SkBitmap bitmap;
// TODO: verify that the CG Context's pixels will have tight rowbytes or pass in the correct
// rowbytes for the case when context != NULL.
bitmap.setInfo(SkImageInfo::MakeN32(width, height, is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType));
void* data;
if (context) {
data = CGBitmapContextGetData(context);
bitmap.setPixels(data);
} else {
if (!bitmap.tryAllocPixels())
return NULL;
data = bitmap.getPixels();
}
if (do_clear)
memset(data, 0, bitmap.getSafeSize());
// If we were given data, then don't clobber it!
#ifndef NDEBUG
if (!context && is_opaque) {
// To aid in finding bugs, we set the background color to something
// obviously wrong so it will be noticable when it is not cleared
bitmap.eraseARGB(255, 0, 255, 128); // bright bluish green
}
#endif
if (!context) {
context = CGContextForData(data, width, height);
if (!context)
return NULL;
} else
CGContextRetain(context);
BitmapPlatformDevice* rv = new BitmapPlatformDevice(context, bitmap);
// The device object took ownership of the graphics context with its own
// CGContextRetain call.
CGContextRelease(context);
return rv;
}
BitmapPlatformDevice* BitmapPlatformDevice::CreateWithData(uint8_t* data,
int width,
int height,
bool is_opaque) {
CGContextRef context = NULL;
if (data)
context = CGContextForData(data, width, height);
BitmapPlatformDevice* rv = Create(context, width, height, is_opaque, false);
// The device object took ownership of the graphics context with its own
// CGContextRetain call.
if (context)
CGContextRelease(context);
return rv;
}
// The device will own the bitmap, which corresponds to also owning the pixel
// data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap.
BitmapPlatformDevice::BitmapPlatformDevice(
CGContextRef context, const SkBitmap& bitmap)
: SkBitmapDevice(bitmap),
bitmap_context_(context) {
SetPlatformDevice(this, this);
SkASSERT(bitmap_context_);
// Initialize the clip region to the entire bitmap.
SkIRect rect;
rect.set(0, 0,
CGBitmapContextGetWidth(bitmap_context_),
CGBitmapContextGetHeight(bitmap_context_));
CGContextRetain(bitmap_context_);
// We must save the state once so that we can use the restore/save trick
// in LoadConfig().
CGContextSaveGState(bitmap_context_);
}
BitmapPlatformDevice::~BitmapPlatformDevice() {
if (bitmap_context_)
CGContextRelease(bitmap_context_);
}
NativeDrawingContext BitmapPlatformDevice::BeginPlatformPaint(
const SkMatrix& transform,
const SkIRect& clip_bounds) {
LoadConfig(transform, clip_bounds);
return bitmap_context_;
}
SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& cinfo,
const SkPaint*) {
const SkImageInfo& info = cinfo.fInfo;
const bool do_clear = !info.isOpaque();
SkASSERT(info.colorType() == kN32_SkColorType);
return Create(NULL, info.width(), info.height(), info.isOpaque(), do_clear);
}
// PlatformCanvas impl
std::unique_ptr<SkCanvas> CreatePlatformCanvasWithPixels(
int width,
int height,
bool is_opaque,
uint8_t* data,
OnFailureType failureType) {
sk_sp<SkBaseDevice> dev(
BitmapPlatformDevice::CreateWithData(data, width, height, is_opaque));
return CreateCanvas(dev, failureType);
}
} // namespace skia
// Copyright (c) 2012 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.
#ifndef SKIA_EXT_BITMAP_PLATFORM_DEVICE_MAC_H_
#define SKIA_EXT_BITMAP_PLATFORM_DEVICE_MAC_H_
#include <stdint.h>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "skia/ext/platform_device.h"
namespace skia {
// A device is basically a wrapper around SkBitmap that provides a surface for
// SkCanvas to draw into. Our device provides a surface CoreGraphics can also
// write to. BitmapPlatformDevice creates a bitmap using
// CGCreateBitmapContext() in a format that Skia supports and can then use this
// to draw text into, etc. This pixel data is provided to the bitmap that the
// device contains so that it can be shared.
//
// The device owns the pixel data, when the device goes away, the pixel data
// also becomes invalid. THIS IS DIFFERENT THAN NORMAL SKIA which uses
// reference counting for the pixel data. In normal Skia, you could assign
// another bitmap to this device's bitmap and everything will work properly.
// For us, that other bitmap will become invalid as soon as the device becomes
// invalid, which may lead to subtle bugs. Therefore, DO NOT ASSIGN THE
// DEVICE'S PIXEL DATA TO ANOTHER BITMAP, make sure you copy instead.
class SK_API BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
public:
// Creates a BitmapPlatformDevice instance. |is_opaque| should be set if the
// caller knows the bitmap will be completely opaque and allows some
// optimizations.
// |context| may be NULL. If |context| is NULL, then the bitmap backing store
// is not initialized.
static BitmapPlatformDevice* Create(CGContextRef context,
int width, int height,
bool is_opaque, bool do_clear = false);
// Creates a context for |data| and calls Create.
// If |data| is NULL, then the bitmap backing store is not initialized.
static BitmapPlatformDevice* CreateWithData(uint8_t* data,
int width, int height,
bool is_opaque);
~BitmapPlatformDevice() override;
protected:
BitmapPlatformDevice(CGContextRef context,
const SkBitmap& bitmap);
SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
private:
NativeDrawingContext BeginPlatformPaint(const SkMatrix& transform,
const SkIRect& clip_bounds) override;
void ReleaseBitmapContext();
// Loads the current transform and clip into the context. Can be called even
// when |bitmap_context_| is NULL (will be a NOP).
void LoadConfig(const SkMatrix& transform, const SkIRect& clip_bounds);
// Lazily-created graphics context used to draw into the bitmap.
CGContextRef bitmap_context_;
DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice);
};
} // namespace skia
#endif // SKIA_EXT_BITMAP_PLATFORM_DEVICE_MAC_H_
...@@ -9,7 +9,15 @@ namespace skia { ...@@ -9,7 +9,15 @@ namespace skia {
BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height, BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
bool is_opaque) { bool is_opaque) {
return Create(width, height, is_opaque, nullptr); SkBitmap bitmap;
if (bitmap.tryAllocN32Pixels(width, height, is_opaque)) {
// Follow the logic in SkCanvas::createDevice(), initialize the bitmap if it
// is not opaque.
if (!is_opaque)
bitmap.eraseARGB(0, 0, 0, 0);
return new BitmapPlatformDevice(bitmap);
}
return NULL;
} }
BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height, BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
...@@ -18,17 +26,10 @@ BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height, ...@@ -18,17 +26,10 @@ BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
SkBitmap bitmap; SkBitmap bitmap;
bitmap.setInfo(SkImageInfo::MakeN32(width, height, bitmap.setInfo(SkImageInfo::MakeN32(width, height,
is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType)); is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType));
if (data)
if (data) {
bitmap.setPixels(data); bitmap.setPixels(data);
} else { else if (!bitmap.tryAllocPixels())
if (!bitmap.tryAllocPixels()) return NULL;
return nullptr;
// Follow the logic in SkCanvas::createDevice(), initialize the bitmap if
// it is not opaque.
if (!is_opaque)
bitmap.eraseARGB(0, 0, 0, 0);
}
return new BitmapPlatformDevice(bitmap); return new BitmapPlatformDevice(bitmap);
} }
...@@ -48,6 +49,15 @@ SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& info, ...@@ -48,6 +49,15 @@ SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& info,
info.fInfo.isOpaque()); info.fInfo.isOpaque());
} }
NativeDrawingContext BitmapPlatformDevice::BeginPlatformPaint(
const SkMatrix& transform,
const SkIRect& clip_bounds) {
// TODO(zhenghao): What should we return? The ptr to the address of the
// pixels? Maybe this won't be called at all.
SkPixmap pixmap;
return accessPixels(&pixmap) ? pixmap.writable_addr() : nullptr;
}
// PlatformCanvas impl // PlatformCanvas impl
std::unique_ptr<SkCanvas> CreatePlatformCanvasWithPixels( std::unique_ptr<SkCanvas> CreatePlatformCanvasWithPixels(
......
...@@ -21,21 +21,15 @@ namespace skia { ...@@ -21,21 +21,15 @@ namespace skia {
// shared memory between the renderer and the main process at least. In this // shared memory between the renderer and the main process at least. In this
// case we'll probably create the buffer from a precreated region of memory. // case we'll probably create the buffer from a precreated region of memory.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
class BitmapPlatformDevice final : public SkBitmapDevice, class BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
public PlatformDevice {
public: public:
// Construct a BitmapPlatformDevice. |is_opaque| should be set if the caller // Construct a BitmapPlatformDevice. |is_opaque| should be set if the caller
// knows the bitmap will be completely opaque and allows some optimizations // knows the bitmap will be completely opaque and allows some optimizations.
// (the bitmap is not initialized to 0 when is_opaque == true). // The bitmap is not initialized.
static BitmapPlatformDevice* Create(int width, int height, bool is_opaque); static BitmapPlatformDevice* Create(int width, int height, bool is_opaque);
// This doesn't take ownership of |data|. If |data| is null and |is_opaque| // This doesn't take ownership of |data|. If |data| is null, the bitmap
// is false, the bitmap is initialized to 0. // is not initialized to 0.
//
// Note: historicaly, BitmapPlatformDevice impls have had diverging
// initialization behavior for null |data| (Cairo used to initialize, while
// the others did not). For now we stick to the more conservative Cairo
// behavior.
static BitmapPlatformDevice* Create(int width, int height, bool is_opaque, static BitmapPlatformDevice* Create(int width, int height, bool is_opaque,
uint8_t* data); uint8_t* data);
...@@ -50,6 +44,9 @@ class BitmapPlatformDevice final : public SkBitmapDevice, ...@@ -50,6 +44,9 @@ class BitmapPlatformDevice final : public SkBitmapDevice,
SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override; SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
private: private:
NativeDrawingContext BeginPlatformPaint(const SkMatrix& transform,
const SkIRect& clip_bounds) override;
DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice); DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice);
}; };
......
...@@ -17,8 +17,8 @@ namespace skia { ...@@ -17,8 +17,8 @@ namespace skia {
// format that Skia supports and can then use this to draw ClearType into, etc. // format that Skia supports and can then use this to draw ClearType into, etc.
// This pixel data is provided to the bitmap that the device contains so that it // This pixel data is provided to the bitmap that the device contains so that it
// can be shared. // can be shared.
class SK_API BitmapPlatformDevice final : public SkBitmapDevice, class SK_API BitmapPlatformDevice : public SkBitmapDevice,
public PlatformDevice { public PlatformDevice {
public: public:
// Factory function. is_opaque should be set if the caller knows the bitmap // Factory function. is_opaque should be set if the caller knows the bitmap
// will be completely opaque and allows some optimizations. // will be completely opaque and allows some optimizations.
......
...@@ -46,14 +46,11 @@ class SK_API PlatformDevice { ...@@ -46,14 +46,11 @@ class SK_API PlatformDevice {
public: public:
virtual ~PlatformDevice(); virtual ~PlatformDevice();
// Only implemented in bitmap_platform_device_win.
#if defined(WIN32)
// The DC that corresponds to the bitmap, used for GDI operations drawing // The DC that corresponds to the bitmap, used for GDI operations drawing
// into the bitmap. This is possibly heavyweight, so it should be existant // into the bitmap. This is possibly heavyweight, so it should be existant
// only during one pass of rendering. // only during one pass of rendering.
virtual NativeDrawingContext BeginPlatformPaint(const SkMatrix& transform, virtual NativeDrawingContext BeginPlatformPaint(const SkMatrix& transform,
const SkIRect& clip_bounds) = 0; const SkIRect& clip_bounds) = 0;
#endif
}; };
} // namespace skia } // namespace skia
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "base/win/scoped_select_object.h" #include "base/win/scoped_select_object.h"
#include "base/win/win_util.h" #include "base/win/win_util.h"
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
#include "skia/ext/bitmap_platform_device.h"
#include "skia/ext/platform_canvas.h" #include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_win.h" #include "skia/ext/skia_utils_win.h"
#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkCanvas.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment