From 9abceb78361ca70703fdf6051eb4e556f06f2b6a Mon Sep 17 00:00:00 2001
From: "senorblanco@chromium.org"
 <senorblanco@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Mon, 2 Dec 2013 22:44:07 +0000
Subject: Remove BitmapPlatformDeviceData, and merge its functionality into the
 appropriate BitmapPlatformDevice. It was a little twisty maze of #ifdefs,
 ostensibly created to allow successful assignment and copy construction of
 the device. However, I could not find any such use, and the
 BitmapPlatformDevices are all marked DISALLOW_COPY_AND_ASSIGN!

Instead, we use a subclass of SkPixelRef to handle ownership of the platform-specific bitmaps. This allows correct Skia semantics: the SkBitmap used for device drawing can safely outlive the device, since it is refcounted. Such a subclass already existed for Windows; this simply implements it for Cairo as well, and uses it in all cases.

TBR=brettw

Review URL: https://codereview.chromium.org/95773002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238213 0039d316-1c4b-4281-b951-d872f2087c98
---
 skia/ext/bitmap_platform_device_cairo.cc |  97 +++++++++++++++++------------
 skia/ext/bitmap_platform_device_cairo.h  |  29 +++++++--
 skia/ext/bitmap_platform_device_data.h   | 102 -------------------------------
 skia/ext/bitmap_platform_device_mac.cc   |  67 +++++++++-----------
 skia/ext/bitmap_platform_device_mac.h    |  35 ++++++++---
 skia/ext/bitmap_platform_device_win.cc   |  76 ++++++++++-------------
 skia/ext/bitmap_platform_device_win.h    |  58 ++++++++++++------
 skia/skia_chrome.gypi                    |   1 -
 8 files changed, 212 insertions(+), 253 deletions(-)
 delete mode 100644 skia/ext/bitmap_platform_device_data.h

(limited to 'skia')

diff --git a/skia/ext/bitmap_platform_device_cairo.cc b/skia/ext/bitmap_platform_device_cairo.cc
index e931629..906f95c 100644
--- a/skia/ext/bitmap_platform_device_cairo.cc
+++ b/skia/ext/bitmap_platform_device_cairo.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "skia/ext/bitmap_platform_device_cairo.h"
-#include "skia/ext/bitmap_platform_device_data.h"
 #include "skia/ext/platform_canvas.h"
 
 #if defined(OS_OPENBSD)
@@ -16,6 +15,42 @@ namespace skia {
 
 namespace {
 
+// CairoSurfacePixelRef is an SkPixelRef that is backed by a cairo surface.
+class SK_API CairoSurfacePixelRef : public SkPixelRef {
+ public:
+  // The constructor takes ownership of the passed-in surface.
+  explicit CairoSurfacePixelRef(cairo_surface_t* surface);
+  virtual ~CairoSurfacePixelRef();
+
+  SK_DECLARE_UNFLATTENABLE_OBJECT();
+
+ protected:
+  virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
+  virtual void onUnlockPixels() SK_OVERRIDE;
+
+ private:
+  cairo_surface_t* surface_;
+};
+
+CairoSurfacePixelRef::CairoSurfacePixelRef(cairo_surface_t* surface)
+    : surface_(surface) {
+}
+
+CairoSurfacePixelRef::~CairoSurfacePixelRef() {
+  if (surface_)
+    cairo_surface_destroy(surface_);
+}
+
+void* CairoSurfacePixelRef::onLockPixels(SkColorTable** color_table) {
+  *color_table = NULL;
+  return cairo_image_surface_get_data(surface_);
+}
+
+void CairoSurfacePixelRef::onUnlockPixels() {
+  // Nothing to do.
+  return;
+}
+
 void LoadMatrixToContext(cairo_t* context, const SkMatrix& matrix) {
   cairo_matrix_t cairo_matrix;
   cairo_matrix_init(&cairo_matrix,
@@ -41,20 +76,7 @@ void LoadClipToContext(cairo_t* context, const SkRegion& clip) {
 
 }  // namespace
 
-BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData(
-    cairo_surface_t* surface)
-    : surface_(surface),
-      config_dirty_(true),
-      transform_(SkMatrix::I()) {  // Want to load the config next time.
-  bitmap_context_ = cairo_create(surface);
-}
-
-BitmapPlatformDevice::BitmapPlatformDeviceData::~BitmapPlatformDeviceData() {
-  cairo_destroy(bitmap_context_);
-  cairo_surface_destroy(surface_);
-}
-
-void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip(
+void BitmapPlatformDevice::SetMatrixClip(
     const SkMatrix& transform,
     const SkRegion& region) {
   transform_ = transform;
@@ -62,18 +84,18 @@ void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip(
   config_dirty_ = true;
 }
 
-void BitmapPlatformDevice::BitmapPlatformDeviceData::LoadConfig() {
-  if (!config_dirty_ || !bitmap_context_)
+void BitmapPlatformDevice::LoadConfig() {
+  if (!config_dirty_ || !cairo_)
     return;  // Nothing to do.
   config_dirty_ = false;
 
   // Load the identity matrix since this is what our clip is relative to.
   cairo_matrix_t cairo_matrix;
   cairo_matrix_init_identity(&cairo_matrix);
-  cairo_set_matrix(bitmap_context_, &cairo_matrix);
+  cairo_set_matrix(cairo_, &cairo_matrix);
 
-  LoadClipToContext(bitmap_context_, clip_region_);
-  LoadMatrixToContext(bitmap_context_, transform_);
+  LoadClipToContext(cairo_, clip_region_);
+  LoadMatrixToContext(cairo_, transform_);
 }
 
 // We use this static factory function instead of the regular constructor so
@@ -91,11 +113,11 @@ BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
   bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height,
                    cairo_image_surface_get_stride(surface),
                    is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
-  bitmap.setPixels(cairo_image_surface_get_data(surface));
+  RefPtr<SkPixelRef> pixel_ref = AdoptRef(new CairoSurfacePixelRef(surface));
+  bitmap.setPixelRef(pixel_ref.get());
 
   // The device object will take ownership of the graphics context.
-  return new BitmapPlatformDevice
-      (bitmap, new BitmapPlatformDeviceData(surface));
+  return new BitmapPlatformDevice(bitmap, surface);
 }
 
 BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
@@ -136,13 +158,16 @@ BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
 // data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap.
 BitmapPlatformDevice::BitmapPlatformDevice(
     const SkBitmap& bitmap,
-    BitmapPlatformDeviceData* data)
+    cairo_surface_t* surface)
     : SkBitmapDevice(bitmap),
-      data_(data) {
+      cairo_(cairo_create(surface)),
+      config_dirty_(true),
+      transform_(SkMatrix::I()) {  // Want to load the config next time.
   SetPlatformDevice(this, this);
 }
 
 BitmapPlatformDevice::~BitmapPlatformDevice() {
+  cairo_destroy(cairo_);
 }
 
 SkBaseDevice* BitmapPlatformDevice::onCreateCompatibleDevice(
@@ -153,15 +178,14 @@ SkBaseDevice* BitmapPlatformDevice::onCreateCompatibleDevice(
 }
 
 cairo_t* BitmapPlatformDevice::BeginPlatformPaint() {
-  data_->LoadConfig();
-  cairo_t* cairo = data_->bitmap_context();
-  cairo_surface_t* surface = cairo_get_target(cairo);
+  LoadConfig();
+  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;
+  return cairo_;
 }
 
 void BitmapPlatformDevice::DrawToNativeContext(
@@ -173,7 +197,7 @@ void BitmapPlatformDevice::DrawToNativeContext(
 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
                                          const SkRegion& region,
                                          const SkClipStack&) {
-  data_->SetMatrixClip(transform, region);
+  SetMatrixClip(transform, region);
 }
 
 // PlatformCanvas impl
@@ -197,22 +221,17 @@ bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
   int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
   bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height, stride,
                     is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
-  if (!bitmap_.allocPixels())  // Using the default allocator.
-    return false;
 
-  cairo_surface_t* surf = cairo_image_surface_create_for_data(
-      reinterpret_cast<unsigned char*>(bitmap_.getPixels()),
+  cairo_surface_t* surf = cairo_image_surface_create(
       CAIRO_FORMAT_ARGB32,
       width,
-      height,
-      stride);
+      height);
   if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) {
     cairo_surface_destroy(surf);
     return false;
   }
-
-  surface_ = cairo_create(surf);
-  cairo_surface_destroy(surf);
+  RefPtr<SkPixelRef> pixel_ref = AdoptRef(new CairoSurfacePixelRef(surf));
+  bitmap_.setPixelRef(pixel_ref.get());
   return true;
 }
 
diff --git a/skia/ext/bitmap_platform_device_cairo.h b/skia/ext/bitmap_platform_device_cairo.h
index 914be34..5b3c46c 100644
--- a/skia/ext/bitmap_platform_device_cairo.h
+++ b/skia/ext/bitmap_platform_device_cairo.h
@@ -57,9 +57,6 @@ namespace skia {
 // case we'll probably create the buffer from a precreated region of memory.
 // -----------------------------------------------------------------------------
 class BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
-  // A reference counted cairo surface
-  class BitmapPlatformDeviceData;
-
  public:
   // Create a BitmapPlatformDeviceLinux from an already constructed bitmap;
   // you should probably be using Create(). This may become private later if
@@ -67,7 +64,7 @@ class BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
   // the Windows and Mac versions of this class do.
   //
   // This object takes ownership of @data.
-  BitmapPlatformDevice(const SkBitmap& other, BitmapPlatformDeviceData* data);
+  BitmapPlatformDevice(const SkBitmap& other, cairo_surface_t* surface);
   virtual ~BitmapPlatformDevice();
 
   // Constructs a device with size |width| * |height| with contents initialized
@@ -104,7 +101,29 @@ class BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
   static BitmapPlatformDevice* Create(int width, int height, bool is_opaque,
                                       cairo_surface_t* surface);
 
-  scoped_refptr<BitmapPlatformDeviceData> data_;
+  // Sets the transform and clip operations. This will not update the Cairo
+  // context, but will mark the config as dirty. The next call of LoadConfig
+  // will pick up these changes.
+  void SetMatrixClip(const SkMatrix& transform, const SkRegion& region);
+
+  // Loads the current transform and clip into the context.
+  void LoadConfig();
+
+  // Graphics context used to draw into the surface.
+  cairo_t* cairo_;
+
+  // True when there is a transform or clip that has not been set to the
+  // context.  The context is retrieved for every text operation, and the
+  // transform and clip do not change as much. We can save time by not loading
+  // the clip and transform for every one.
+  bool config_dirty_;
+
+  // Translation assigned to the context: we need to keep track of this
+  // separately so it can be updated even if the context isn't created yet.
+  SkMatrix transform_;
+
+  // The current clipping
+  SkRegion clip_region_;
 
   DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice);
 };
diff --git a/skia/ext/bitmap_platform_device_data.h b/skia/ext/bitmap_platform_device_data.h
deleted file mode 100644
index 81e81ed7..0000000
--- a/skia/ext/bitmap_platform_device_data.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2011 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_DATA_H_
-#define SKIA_EXT_BITMAP_PLATFORM_DEVICE_DATA_H_
-
-#include "skia/ext/bitmap_platform_device.h"
-
-namespace skia {
-
-class BitmapPlatformDevice::BitmapPlatformDeviceData :
-#if defined(WIN32) || defined(__APPLE__)
-    public SkRefCnt {
-#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun)
-    // These objects are reference counted and own a Cairo surface. The surface
-    // is the backing store for a Skia bitmap and we reference count it so that
-    // we can copy BitmapPlatformDevice objects without having to copy all the
-    // image data.
-    public base::RefCounted<BitmapPlatformDeviceData> {
-#endif
-
- public:
-#if defined(WIN32)
-  typedef HBITMAP PlatformContext;
-#elif defined(__APPLE__)
-  typedef CGContextRef PlatformContext;
-#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun)
-  typedef cairo_t* PlatformContext;
-#endif
-
-#if defined(WIN32) || defined(__APPLE__)
-  explicit BitmapPlatformDeviceData(PlatformContext bitmap);
-#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun)
-  explicit BitmapPlatformDeviceData(cairo_surface_t* surface);
-#endif
-
-#if defined(WIN32)
-  // Create/destroy hdc_, which is the memory DC for our bitmap data.
-  HDC GetBitmapDC();
-  void ReleaseBitmapDC();
-  bool IsBitmapDCCreated() const;
-#endif
-
-#if defined(__APPLE__)
-  void ReleaseBitmapContext();
-#endif  // defined(__APPLE__)
-
-  // Sets the transform and clip operations. This will not update the CGContext,
-  // but will mark the config as dirty. The next call of LoadConfig will
-  // pick up these changes.
-  void SetMatrixClip(const SkMatrix& transform, const SkRegion& region);
-
-  // 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 {
-    return transform_;
-  }
-
-  PlatformContext bitmap_context() {
-    return bitmap_context_;
-  }
-
- private:
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun)
-  friend class base::RefCounted<BitmapPlatformDeviceData>;
-#endif
-  virtual ~BitmapPlatformDeviceData();
-
-  // Lazily-created graphics context used to draw into the bitmap.
-  PlatformContext bitmap_context_;
-
-#if defined(WIN32)
-  // Lazily-created DC used to draw into the bitmap, see GetBitmapDC().
-  HDC hdc_;
-#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun)
-  cairo_surface_t *const surface_;
-#endif
-
-  // True when there is a transform or clip that has not been set to the
-  // context.  The context is retrieved for every text operation, and the
-  // transform and clip do not change as much. We can save time by not loading
-  // the clip and transform for every one.
-  bool config_dirty_;
-
-  // Translation assigned to the context: we need to keep track of this
-  // separately so it can be updated even if the context isn't created yet.
-  SkMatrix transform_;
-
-  // The current clipping
-  SkRegion clip_region_;
-
-  // Disallow copy & assign.
-  BitmapPlatformDeviceData(const BitmapPlatformDeviceData&);
-  BitmapPlatformDeviceData& operator=(const BitmapPlatformDeviceData&);
-};
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_BITMAP_PLATFORM_DEVICE_DATA_H_
diff --git a/skia/ext/bitmap_platform_device_mac.cc b/skia/ext/bitmap_platform_device_mac.cc
index 8525cd3..a62c3cf 100644
--- a/skia/ext/bitmap_platform_device_mac.cc
+++ b/skia/ext/bitmap_platform_device_mac.cc
@@ -9,7 +9,7 @@
 
 #include "base/mac/mac_util.h"
 #include "base/memory/ref_counted.h"
-#include "skia/ext/bitmap_platform_device_data.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"
@@ -57,37 +57,13 @@ static CGContextRef CGContextForData(void* data, int width, int height) {
 
 }  // namespace
 
-BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData(
-    CGContextRef bitmap)
-    : bitmap_context_(bitmap),
-      config_dirty_(true),  // Want to load the config next time.
-      transform_(SkMatrix::I()) {
-  SkASSERT(bitmap_context_);
-  // Initialize the clip region to the entire bitmap.
-
-  SkIRect rect;
-  rect.set(0, 0,
-           CGBitmapContextGetWidth(bitmap_context_),
-           CGBitmapContextGetHeight(bitmap_context_));
-  clip_region_ = SkRegion(rect);
-  CGContextRetain(bitmap_context_);
-  // We must save the state once so that we can use the restore/save trick
-  // in LoadConfig().
-  CGContextSaveGState(bitmap_context_);
-}
-
-BitmapPlatformDevice::BitmapPlatformDeviceData::~BitmapPlatformDeviceData() {
-  if (bitmap_context_)
-    CGContextRelease(bitmap_context_);
-}
-
-void BitmapPlatformDevice::BitmapPlatformDeviceData::ReleaseBitmapContext() {
+void BitmapPlatformDevice::ReleaseBitmapContext() {
   SkASSERT(bitmap_context_);
   CGContextRelease(bitmap_context_);
   bitmap_context_ = NULL;
 }
 
-void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip(
+void BitmapPlatformDevice::SetMatrixClip(
     const SkMatrix& transform,
     const SkRegion& region) {
   transform_ = transform;
@@ -95,7 +71,7 @@ void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip(
   config_dirty_ = true;
 }
 
-void BitmapPlatformDevice::BitmapPlatformDeviceData::LoadConfig() {
+void BitmapPlatformDevice::LoadConfig() {
   if (!config_dirty_ || !bitmap_context_)
     return;  // Nothing to do.
   config_dirty_ = false;
@@ -156,8 +132,7 @@ BitmapPlatformDevice* BitmapPlatformDevice::Create(CGContextRef context,
   } else
     CGContextRetain(context);
 
-  BitmapPlatformDevice* rv = new BitmapPlatformDevice(
-      skia::AdoptRef(new BitmapPlatformDeviceData(context)), bitmap);
+  BitmapPlatformDevice* rv = new BitmapPlatformDevice(context, bitmap);
 
   // The device object took ownership of the graphics context with its own
   // CGContextRetain call.
@@ -196,37 +171,53 @@ BitmapPlatformDevice* BitmapPlatformDevice::CreateWithData(uint8_t* data,
 // 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(
-    const skia::RefPtr<BitmapPlatformDeviceData>& data, const SkBitmap& bitmap)
+    CGContextRef context, const SkBitmap& bitmap)
     : SkBitmapDevice(bitmap),
-      data_(data) {
+      bitmap_context_(context),
+      config_dirty_(true),  // Want to load the config next time.
+      transform_(SkMatrix::I()) {
   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_));
+  clip_region_ = SkRegion(rect);
+  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_);
 }
 
 CGContextRef BitmapPlatformDevice::GetBitmapContext() {
-  data_->LoadConfig();
-  return data_->bitmap_context();
+  LoadConfig();
+  return bitmap_context_;
 }
 
 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
                                          const SkRegion& region,
                                          const SkClipStack&) {
-  data_->SetMatrixClip(transform, region);
+  SetMatrixClip(transform, region);
 }
 
 void BitmapPlatformDevice::DrawToNativeContext(CGContextRef context, int x,
                                                int y, const CGRect* src_rect) {
   bool created_dc = false;
-  if (!data_->bitmap_context()) {
+  if (!bitmap_context_) {
     created_dc = true;
     GetBitmapContext();
   }
 
   // this should not make a copy of the bits, since we're not doing
   // anything to trigger copy on write
-  CGImageRef image = CGBitmapContextCreateImage(data_->bitmap_context());
+  CGImageRef image = CGBitmapContextCreateImage(bitmap_context_);
   CGRect bounds;
   bounds.origin.x = x;
   bounds.origin.y = y;
@@ -244,7 +235,7 @@ void BitmapPlatformDevice::DrawToNativeContext(CGContextRef context, int x,
   CGImageRelease(image);
 
   if (created_dc)
-    data_->ReleaseBitmapContext();
+    ReleaseBitmapContext();
 }
 
 SkBaseDevice* BitmapPlatformDevice::onCreateCompatibleDevice(
diff --git a/skia/ext/bitmap_platform_device_mac.h b/skia/ext/bitmap_platform_device_mac.h
index 07b0084..00b0309 100644
--- a/skia/ext/bitmap_platform_device_mac.h
+++ b/skia/ext/bitmap_platform_device_mac.h
@@ -60,21 +60,40 @@ class SK_API BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice
                              const SkClipStack&) OVERRIDE;
 
  protected:
-  // Reference counted data that can be shared between multiple devices. This
-  // allows copy constructors and operator= for devices to work properly. The
-  // bitmaps used by the base device class are already refcounted and copyable.
-  class BitmapPlatformDeviceData;
-
-  BitmapPlatformDevice(const skia::RefPtr<BitmapPlatformDeviceData>& data,
+  BitmapPlatformDevice(CGContextRef context,
                        const SkBitmap& bitmap);
 
   virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config, int width,
                                                  int height, bool isOpaque,
                                                  Usage usage) OVERRIDE;
 
-  // Data associated with this device, guaranteed non-null.
-  skia::RefPtr<BitmapPlatformDeviceData> data_;
+ private:
+  void ReleaseBitmapContext();
+
+  // Sets the transform and clip operations. This will not update the CGContext,
+  // but will mark the config as dirty. The next call of LoadConfig will
+  // pick up these changes.
+  void SetMatrixClip(const SkMatrix& transform, const SkRegion& region);
+
+  // Loads the current transform and clip into the context. Can be called even
+  // when |bitmap_context_| is NULL (will be a NOP).
+  void LoadConfig();
+
+  // Lazily-created graphics context used to draw into the bitmap.
+  CGContextRef bitmap_context_;
+
+  // True when there is a transform or clip that has not been set to the
+  // context.  The context is retrieved for every text operation, and the
+  // transform and clip do not change as much. We can save time by not loading
+  // the clip and transform for every one.
+  bool config_dirty_;
+
+  // Translation assigned to the context: we need to keep track of this
+  // separately so it can be updated even if the context isn't created yet.
+  SkMatrix transform_;
 
+  // The current clipping
+  SkRegion clip_region_;
   DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice);
 };
 
diff --git a/skia/ext/bitmap_platform_device_win.cc b/skia/ext/bitmap_platform_device_win.cc
index 42f431b..0dfc324 100644
--- a/skia/ext/bitmap_platform_device_win.cc
+++ b/skia/ext/bitmap_platform_device_win.cc
@@ -8,7 +8,6 @@
 #include "base/logging.h"
 #include "base/debug/alias.h"
 #include "skia/ext/bitmap_platform_device_win.h"
-#include "skia/ext/bitmap_platform_device_data.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkMatrix.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
@@ -144,34 +143,11 @@ void PlatformBitmapPixelRef::onUnlockPixels() {
 
 namespace skia {
 
-BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData(
-    HBITMAP hbitmap)
-    : bitmap_context_(hbitmap),
-      hdc_(NULL),
-      config_dirty_(true),  // Want to load the config next time.
-      transform_(SkMatrix::I()) {
-  // Initialize the clip region to the entire bitmap.
-  BITMAP bitmap_data;
-  if (GetObject(bitmap_context_, sizeof(BITMAP), &bitmap_data)) {
-    SkIRect rect;
-    rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight);
-    clip_region_ = SkRegion(rect);
-  }
-}
-
-BitmapPlatformDevice::BitmapPlatformDeviceData::~BitmapPlatformDeviceData() {
-  if (hdc_)
-    ReleaseBitmapDC();
-
-  // this will free the bitmap data as well as the bitmap handle
-  DeleteObject(bitmap_context_);
-}
-
-HDC BitmapPlatformDevice::BitmapPlatformDeviceData::GetBitmapDC() {
+HDC BitmapPlatformDevice::GetBitmapDC() {
   if (!hdc_) {
     hdc_ = CreateCompatibleDC(NULL);
     InitializeDC(hdc_);
-    HGDIOBJ old_bitmap = SelectObject(hdc_, bitmap_context_);
+    HGDIOBJ old_bitmap = SelectObject(hdc_, hbitmap_);
     // When the memory DC is created, its display surface is exactly one
     // monochrome pixel wide and one monochrome pixel high. Since we select our
     // own bitmap, we must delete the previous one.
@@ -182,19 +158,19 @@ HDC BitmapPlatformDevice::BitmapPlatformDeviceData::GetBitmapDC() {
   return hdc_;
 }
 
-void BitmapPlatformDevice::BitmapPlatformDeviceData::ReleaseBitmapDC() {
+void BitmapPlatformDevice::ReleaseBitmapDC() {
   SkASSERT(hdc_);
   DeleteDC(hdc_);
   hdc_ = NULL;
 }
 
-bool BitmapPlatformDevice::BitmapPlatformDeviceData::IsBitmapDCCreated()
+bool BitmapPlatformDevice::IsBitmapDCCreated()
     const {
   return hdc_ != NULL;
 }
 
 
-void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip(
+void BitmapPlatformDevice::SetMatrixClip(
     const SkMatrix& transform,
     const SkRegion& region) {
   transform_ = transform;
@@ -202,7 +178,7 @@ void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip(
   config_dirty_ = true;
 }
 
-void BitmapPlatformDevice::BitmapPlatformDeviceData::LoadConfig() {
+void BitmapPlatformDevice::LoadConfig() {
   if (!config_dirty_ || !hdc_)
     return;  // Nothing to do.
   config_dirty_ = false;
@@ -231,7 +207,9 @@ BitmapPlatformDevice* BitmapPlatformDevice::Create(
   SkBitmap bitmap;
   bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0,
                    is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
-  bitmap.setPixels(data);
+  RefPtr<SkPixelRef> pixel_ref = AdoptRef(new PlatformBitmapPixelRef(hbitmap,
+                                                                     data));
+  bitmap.setPixelRef(pixel_ref.get());
 
 #ifndef NDEBUG
   // If we were given data, then don't clobber it!
@@ -243,8 +221,7 @@ BitmapPlatformDevice* BitmapPlatformDevice::Create(
 
   // The device object will take ownership of the HBITMAP. The initial refcount
   // of the data object will be 1, which is what the constructor expects.
-  return new BitmapPlatformDevice(
-      skia::AdoptRef(new BitmapPlatformDeviceData(hbitmap)), bitmap);
+  return new BitmapPlatformDevice(hbitmap, bitmap);
 }
 
 // static
@@ -267,22 +244,34 @@ BitmapPlatformDevice* BitmapPlatformDevice::CreateAndClear(int width,
 // The device will own the HBITMAP, which corresponds to also owning the pixel
 // data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap.
 BitmapPlatformDevice::BitmapPlatformDevice(
-    const skia::RefPtr<BitmapPlatformDeviceData>& data,
+    HBITMAP hbitmap,
     const SkBitmap& bitmap)
     : SkBitmapDevice(bitmap),
-      data_(data) {
+      hbitmap_(hbitmap),
+      hdc_(NULL),
+      config_dirty_(true),  // Want to load the config next time.
+      transform_(SkMatrix::I()) {
   // The data object is already ref'ed for us by create().
   SkDEBUGCODE(begin_paint_count_ = 0);
   SetPlatformDevice(this, this);
+  // Initialize the clip region to the entire bitmap.
+  BITMAP bitmap_data;
+  if (GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data)) {
+    SkIRect rect;
+    rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight);
+    clip_region_ = SkRegion(rect);
+  }
 }
 
 BitmapPlatformDevice::~BitmapPlatformDevice() {
   SkASSERT(begin_paint_count_ == 0);
+  if (hdc_)
+    ReleaseBitmapDC();
 }
 
 HDC BitmapPlatformDevice::BeginPlatformPaint() {
   SkDEBUGCODE(begin_paint_count_++);
-  return data_->GetBitmapDC();
+  return GetBitmapDC();
 }
 
 void BitmapPlatformDevice::EndPlatformPaint() {
@@ -293,12 +282,12 @@ void BitmapPlatformDevice::EndPlatformPaint() {
 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
                                          const SkRegion& region,
                                          const SkClipStack&) {
-  data_->SetMatrixClip(transform, region);
+  SetMatrixClip(transform, region);
 }
 
 void BitmapPlatformDevice::DrawToNativeContext(HDC dc, int x, int y,
                                                const RECT* src_rect) {
-  bool created_dc = !data_->IsBitmapDCCreated();
+  bool created_dc = !IsBitmapDCCreated();
   HDC source_dc = BeginPlatformPaint();
 
   RECT temp_rect;
@@ -344,17 +333,17 @@ void BitmapPlatformDevice::DrawToNativeContext(HDC dc, int x, int y,
                   copy_height,
                   blend_function);
   }
-  LoadTransformToDC(source_dc, data_->transform());
+  LoadTransformToDC(source_dc, transform_);
 
   EndPlatformPaint();
   if (created_dc)
-    data_->ReleaseBitmapDC();
+    ReleaseBitmapDC();
 }
 
 const SkBitmap& BitmapPlatformDevice::onAccessBitmap() {
   // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI
   // operation has occurred on our DC.
-  if (data_->IsBitmapDCCreated())
+  if (IsBitmapDCCreated())
     GdiFlush();
   return SkBitmapDevice::onAccessBitmap();
 }
@@ -404,8 +393,9 @@ bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
   bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0,
                     is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
   // PlatformBitmapPixelRef takes ownership of |hbitmap|.
-  bitmap_.setPixelRef(
-      skia::AdoptRef(new PlatformBitmapPixelRef(hbitmap, data)).get());
+  RefPtr<SkPixelRef> pixel_ref = AdoptRef(new PlatformBitmapPixelRef(hbitmap,
+                                                                     data));
+  bitmap_.setPixelRef(pixel_ref.get());
   bitmap_.lockPixels();
 
   return true;
diff --git a/skia/ext/bitmap_platform_device_win.h b/skia/ext/bitmap_platform_device_win.h
index 1261e51..d2c1603 100644
--- a/skia/ext/bitmap_platform_device_win.h
+++ b/skia/ext/bitmap_platform_device_win.h
@@ -19,13 +19,11 @@ namespace skia {
 // 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.
+// The GDI bitmap created for drawing is actually owned by a
+// PlatformBitmapPixelRef, and stored in an SkBitmap via the normal skia
+// SkPixelRef refcounting mechanism. In this way, the GDI bitmap can outlive
+// the device created to draw into it. So it is safe to call accessBitmap() on
+// the device, and retain the returned SkBitmap.
 class SK_API BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
  public:
   // Factory function. is_opaque should be set if the caller knows the bitmap
@@ -75,17 +73,43 @@ class SK_API BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice
                                                  Usage usage) OVERRIDE;
 
  private:
-  // Reference counted data that can be shared between multiple devices. This
-  // allows copy constructors and operator= for devices to work properly. The
-  // bitmaps used by the base device class are already refcounted and copyable.
-  class BitmapPlatformDeviceData;
-
   // Private constructor.
-  BitmapPlatformDevice(const skia::RefPtr<BitmapPlatformDeviceData>& data,
-                       const SkBitmap& bitmap);
-
-  // Data associated with this device, guaranteed non-null.
-  skia::RefPtr<BitmapPlatformDeviceData> data_;
+  BitmapPlatformDevice(HBITMAP hbitmap, const SkBitmap& bitmap);
+
+  // Bitmap into which the drawing will be done. This bitmap not owned by this
+  // class, but by the BitmapPlatformPixelRef inside the device's SkBitmap.
+  // It's only stored here in order to lazy-create the DC (below).
+  HBITMAP hbitmap_;
+
+  // Lazily-created DC used to draw into the bitmap; see GetBitmapDC().
+  HDC hdc_;
+
+  // True when there is a transform or clip that has not been set to the
+  // context.  The context is retrieved for every text operation, and the
+  // transform and clip do not change as much. We can save time by not loading
+  // the clip and transform for every one.
+  bool config_dirty_;
+
+  // Translation assigned to the context: we need to keep track of this
+  // separately so it can be updated even if the context isn't created yet.
+  SkMatrix transform_;
+
+  // The current clipping region.
+  SkRegion clip_region_;
+
+  // Create/destroy hdc_, which is the memory DC for our bitmap data.
+  HDC GetBitmapDC();
+  void ReleaseBitmapDC();
+  bool IsBitmapDCCreated() const;
+
+  // Sets the transform and clip operations. This will not update the DC,
+  // but will mark the config as dirty. The next call of LoadConfig will
+  // pick up these changes.
+  void SetMatrixClip(const SkMatrix& transform, const SkRegion& region);
+
+  // Loads the current transform and clip into the context. Can be called even
+  // when |hbitmap_| is NULL (will be a NOP).
+  void LoadConfig();
 
 #ifdef SK_DEBUG
   int begin_paint_count_;
diff --git a/skia/skia_chrome.gypi b/skia/skia_chrome.gypi
index 32179a6..6dcc665 100644
--- a/skia/skia_chrome.gypi
+++ b/skia/skia_chrome.gypi
@@ -28,7 +28,6 @@
     'ext/bitmap_platform_device.h',
     'ext/bitmap_platform_device_cairo.cc',
     'ext/bitmap_platform_device_cairo.h',
-    'ext/bitmap_platform_device_data.h',
     'ext/bitmap_platform_device_mac.cc',
     'ext/bitmap_platform_device_mac.h',
     'ext/bitmap_platform_device_skia.cc',
-- 
cgit v1.1