From 7f1fe3fad451d8809d94b19fca516a2a2134e38c Mon Sep 17 00:00:00 2001 From: "brettw@chromium.org" Date: Mon, 13 Jul 2009 17:06:53 +0000 Subject: Keep the cairo clipping region in sync with the Skia one. The PlatformCanvas now tracks this, so we don't need to have the similar code in gfx::Canvas. I moved most references of cairo_surface_t to cairo_t since the cairo_t has a transform and clip but the surface does not. Review URL: http://codereview.chromium.org/149409 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20499 0039d316-1c4b-4281-b951-d872f2087c98 --- skia/ext/bitmap_platform_device_linux.cc | 119 ++++++++++++++++++++++++++++--- skia/ext/bitmap_platform_device_linux.h | 8 ++- skia/ext/bitmap_platform_device_win.h | 3 + skia/ext/canvas_paint_linux.h | 11 +-- skia/ext/platform_canvas_linux.cc | 2 +- skia/ext/platform_device_linux.h | 6 +- 6 files changed, 127 insertions(+), 22 deletions(-) (limited to 'skia') diff --git a/skia/ext/bitmap_platform_device_linux.cc b/skia/ext/bitmap_platform_device_linux.cc index 1b061b0..a74ec83 100644 --- a/skia/ext/bitmap_platform_device_linux.cc +++ b/skia/ext/bitmap_platform_device_linux.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -8,6 +8,33 @@ namespace skia { +namespace { + +void LoadMatrixToContext(cairo_t* context, const SkMatrix& matrix) { + cairo_matrix_t cairo_matrix; + cairo_matrix_init(&cairo_matrix, + SkScalarToFloat(matrix.getScaleX()), + SkScalarToFloat(matrix.getSkewY()), + SkScalarToFloat(matrix.getSkewX()), + SkScalarToFloat(matrix.getScaleY()), + SkScalarToFloat(matrix.getTranslateX()), + SkScalarToFloat(matrix.getTranslateY())); + cairo_set_matrix(context, &cairo_matrix); +} + +void LoadClipToContext(cairo_t* context, const SkRegion& clip) { + cairo_reset_clip(context); + + // TODO(brettw) support non-rect clips. + SkIRect bounding = clip.getBounds(); + cairo_rectangle(context, bounding.fLeft, bounding.fTop, + bounding.fRight - bounding.fLeft, + bounding.fBottom - bounding.fTop); + cairo_clip(context); +} + +} // namespace + // ----------------------------------------------------------------------------- // 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 @@ -17,18 +44,39 @@ namespace skia { class BitmapPlatformDevice::BitmapPlatformDeviceData : public base::RefCounted { public: - explicit BitmapPlatformDeviceData(cairo_surface_t* surface) - : surface_(surface) { } + explicit BitmapPlatformDeviceData(cairo_surface_t* surface); - cairo_surface_t* surface() const { return surface_; } + cairo_t* GetContext(); + cairo_surface_t* GetSurface(); + + // Sets the transform and clip operations. This will not update the Cairo + // surface, 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); protected: + friend class base::RefCounted; + + ~BitmapPlatformDeviceData(); + + void LoadConfig(); + + // The Cairo surface inside this DC. + cairo_t* context_; cairo_surface_t *const surface_; - friend class base::RefCounted; - ~BitmapPlatformDeviceData() { - cairo_surface_destroy(surface_); - } + // True when there is a transform or clip that has not been set to the + // surface. The surface 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 DC: we need to keep track of this separately + // so it can be updated even if the DC isn't created yet. + SkMatrix transform_; + + // The current clipping + SkRegion clip_region_; // Disallow copy & assign. BitmapPlatformDeviceData(const BitmapPlatformDeviceData&); @@ -36,6 +84,52 @@ class BitmapPlatformDevice::BitmapPlatformDeviceData const BitmapPlatformDeviceData&); }; +BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData( + cairo_surface_t* surface) + : surface_(surface), + config_dirty_(true) { // Want to load the config next time. + context_ = cairo_create(surface); +} + +BitmapPlatformDevice::BitmapPlatformDeviceData::~BitmapPlatformDeviceData() { + cairo_destroy(context_); + cairo_surface_destroy(surface_); +} + +cairo_t* BitmapPlatformDevice::BitmapPlatformDeviceData::GetContext() { + LoadConfig(); + return context_; +} + +void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip( + const SkMatrix& transform, + const SkRegion& region) { + transform_ = transform; + clip_region_ = region; + config_dirty_ = true; +} + +cairo_surface_t* +BitmapPlatformDevice::BitmapPlatformDeviceData::GetSurface() { + // TODO(brettw) this function should be removed. + LoadConfig(); + return surface_; +} + +void BitmapPlatformDevice::BitmapPlatformDeviceData::LoadConfig() { + if (!config_dirty_ || !context_) + 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(context_, &cairo_matrix); + + LoadClipToContext(context_, clip_region_); + LoadMatrixToContext(context_, 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 @@ -98,8 +192,13 @@ BitmapPlatformDevice::BitmapPlatformDevice( BitmapPlatformDevice::~BitmapPlatformDevice() { } -cairo_surface_t* BitmapPlatformDevice::surface() const { - return data_->surface(); +cairo_t* BitmapPlatformDevice::beginPlatformPaint() { + return data_->GetContext(); +} + +void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform, + const SkRegion& region) { + data_->SetMatrixClip(transform, region); } BitmapPlatformDevice& BitmapPlatformDevice::operator=( diff --git a/skia/ext/bitmap_platform_device_linux.h b/skia/ext/bitmap_platform_device_linux.h index a40986c..eb6ffa9 100644 --- a/skia/ext/bitmap_platform_device_linux.h +++ b/skia/ext/bitmap_platform_device_linux.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -85,9 +85,11 @@ class BitmapPlatformDevice : public PlatformDevice { // If someone wants to paint on a Cairo surface version of our // buffer, then give them the surface we're already using. - virtual cairo_surface_t* beginPlatformPaint() { return surface(); } + virtual cairo_t* beginPlatformPaint(); - cairo_surface_t* surface() const; + // Loads the given transform and clipping region into the HDC. This is + // overridden from SkDevice. + virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region); private: scoped_refptr data_; diff --git a/skia/ext/bitmap_platform_device_win.h b/skia/ext/bitmap_platform_device_win.h index b37792a..7093ff1 100644 --- a/skia/ext/bitmap_platform_device_win.h +++ b/skia/ext/bitmap_platform_device_win.h @@ -64,6 +64,9 @@ class BitmapPlatformDevice : public PlatformDevice { // Retrieves the bitmap DC, which is the memory DC for our bitmap data. The // bitmap DC is lazy created. virtual HDC getBitmapDC(); + + // Loads the given transform and clipping region into the HDC. This is + // overridden from SkDevice. virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region); virtual void drawToHDC(HDC dc, int x, int y, const RECT* src_rect); diff --git a/skia/ext/canvas_paint_linux.h b/skia/ext/canvas_paint_linux.h index 361254b..abb6ada 100644 --- a/skia/ext/canvas_paint_linux.h +++ b/skia/ext/canvas_paint_linux.h @@ -21,7 +21,7 @@ class CanvasPaintT : public T { public: // This constructor assumes the result is opaque. explicit CanvasPaintT(GdkEventExpose* event) - : surface_(NULL), + : context_(NULL), window_(event->window), rectangle_(event->area), composite_alpha_(false) { @@ -29,7 +29,7 @@ class CanvasPaintT : public T { } CanvasPaintT(GdkEventExpose* event, bool opaque) - : surface_(NULL), + : context_(NULL), window_(event->window), rectangle_(event->area), composite_alpha_(false) { @@ -44,7 +44,8 @@ class CanvasPaintT : public T { cairo_t* cr = gdk_cairo_create(window_); if (composite_alpha_) cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_surface(cr, surface_, rectangle_.x, rectangle_.y); + cairo_surface_t* source_surface = cairo_get_target(context_); + cairo_set_source_surface(cr, source_surface, rectangle_.x, rectangle_.y); cairo_rectangle(cr, rectangle_.x, rectangle_.y, rectangle_.width, rectangle_.height); cairo_fill(cr); @@ -80,10 +81,10 @@ class CanvasPaintT : public T { // surface. T::translate(-SkIntToScalar(rectangle_.x), -SkIntToScalar(rectangle_.y)); - surface_ = T::getTopPlatformDevice().beginPlatformPaint(); + context_ = T::getTopPlatformDevice().beginPlatformPaint(); } - cairo_surface_t* surface_; + cairo_t* context_; GdkWindow* window_; GdkRectangle rectangle_; // See description above setter. diff --git a/skia/ext/platform_canvas_linux.cc b/skia/ext/platform_canvas_linux.cc index 61e8404..109b232 100644 --- a/skia/ext/platform_canvas_linux.cc +++ b/skia/ext/platform_canvas_linux.cc @@ -42,7 +42,7 @@ bool PlatformCanvas::initialize(int width, int height, bool is_opaque, return true; } -cairo_surface_t* PlatformCanvas::beginPlatformPaint() { +cairo_t* PlatformCanvas::beginPlatformPaint() { return getTopPlatformDevice().beginPlatformPaint(); } diff --git a/skia/ext/platform_device_linux.h b/skia/ext/platform_device_linux.h index c23a4d8..2a08cc8 100644 --- a/skia/ext/platform_device_linux.h +++ b/skia/ext/platform_device_linux.h @@ -7,19 +7,19 @@ #include "third_party/skia/include/core/SkDevice.h" -typedef struct _cairo_surface cairo_surface_t; +typedef struct _cairo cairo_t; namespace skia { // Blindly copying the mac hierarchy. class PlatformDevice : public SkDevice { public: - typedef cairo_surface_t* PlatformSurface; + typedef cairo_t* PlatformSurface; // Returns if the preferred rendering engine is vectorial or bitmap based. virtual bool IsVectorial() = 0; - virtual cairo_surface_t* beginPlatformPaint() = 0; + virtual PlatformSurface beginPlatformPaint() = 0; protected: // Forwards |bitmap| to SkDevice's constructor. -- cgit v1.1