diff options
author | jeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-29 23:40:02 +0000 |
---|---|---|
committer | jeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-29 23:40:02 +0000 |
commit | 6e9d0ce099bde00d35abc8a8deef0ad728efda7e (patch) | |
tree | 5e3423bd964bad498d275d79303fdf9fc12c3a39 /base/gfx | |
parent | 7be5131b5e012054c7a162a95f3b3cc0793c5e34 (diff) | |
download | chromium_src-6e9d0ce099bde00d35abc8a8deef0ad728efda7e.zip chromium_src-6e9d0ce099bde00d35abc8a8deef0ad728efda7e.tar.gz chromium_src-6e9d0ce099bde00d35abc8a8deef0ad728efda7e.tar.bz2 |
Sync Mac canvas implementation with Windows version, still a work in progress,
not all unit tests pass yet.
Review URL: http://codereview.chromium.org/4339
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2702 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/gfx')
-rwxr-xr-x | base/gfx/bitmap_platform_device_mac.cc | 62 | ||||
-rwxr-xr-x | base/gfx/bitmap_platform_device_mac.h | 7 | ||||
-rwxr-xr-x | base/gfx/platform_canvas_mac.cc | 73 | ||||
-rwxr-xr-x | base/gfx/platform_canvas_mac.h | 19 | ||||
-rwxr-xr-x | base/gfx/platform_device_mac.cc | 67 | ||||
-rwxr-xr-x | base/gfx/platform_device_mac.h | 12 |
6 files changed, 102 insertions, 138 deletions
diff --git a/base/gfx/bitmap_platform_device_mac.cc b/base/gfx/bitmap_platform_device_mac.cc index 0bae190..40b58cf 100755 --- a/base/gfx/bitmap_platform_device_mac.cc +++ b/base/gfx/bitmap_platform_device_mac.cc @@ -52,6 +52,7 @@ class BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData // Create/destroy CoreGraphics context for our bitmap data. CGContextRef GetBitmapContext() { + LoadConfig(); return bitmap_context_; } @@ -64,8 +65,7 @@ class BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData // 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 SetTransform(const SkMatrix& t); - void SetClipRegion(const SkRegion& region); + void SetMatrixClip(const SkMatrix& transform, const SkRegion& region); // Loads the current transform and clip into the DC. Can be called even when // |bitmap_context_| is NULL (will be a NOP). @@ -109,19 +109,15 @@ BitmapPlatformDeviceMac::\ rect.set(0, 0, CGBitmapContextGetWidth(bitmap_context_), CGBitmapContextGetHeight(bitmap_context_)); - SkRegion region(rect); - SetClipRegion(region); + clip_region_ = SkRegion(rect); + transform_.reset(); CGContextRetain(bitmap_context_); } -void BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData::SetTransform( - const SkMatrix& t) { - transform_ = t; - config_dirty_ = true; -} - -void BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData::SetClipRegion( +void BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData::SetMatrixClip( + const SkMatrix& transform, const SkRegion& region) { + transform_ = transform; clip_region_ = region; config_dirty_ = true; } @@ -134,11 +130,10 @@ void BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData::LoadConfig() { // Transform. SkMatrix t(transform_); LoadTransformToCGContext(bitmap_context_, t); - - // TODO(brettw) we should support more than just rect clipping here. - SkIRect rect = clip_region_.getBounds(); - - CGContextClipToRect(bitmap_context_, SkIRectToCGRect(rect)); + + t.setTranslateX(-t.getTranslateX()); + t.setTranslateY(-t.getTranslateY()); + LoadClippingRegionToCGContext(bitmap_context_, clip_region_, t); } @@ -150,6 +145,8 @@ BitmapPlatformDeviceMac* BitmapPlatformDeviceMac::Create(CGContextRef context, int width, int height, bool is_opaque) { + // TODO(playmobil): remove debug code. + //printf("BitmapPlatformDeviceMac::Create(%d,%d)\n", width, height); // each pixel is 4 bytes (RGBA): void* data = malloc(height * width * 4); if (!data) return NULL; @@ -214,12 +211,9 @@ CGContextRef BitmapPlatformDeviceMac::GetBitmapContext() { return data_->GetBitmapContext(); } -void BitmapPlatformDeviceMac::SetTransform(const SkMatrix& matrix) { - data_->SetTransform(matrix); -} - -void BitmapPlatformDeviceMac::SetClipRegion(const SkRegion& region) { - data_->SetClipRegion(region); +void BitmapPlatformDeviceMac::setMatrixClip(const SkMatrix& transform, + const SkRegion& region) { + data_->SetMatrixClip(transform, region); } void BitmapPlatformDeviceMac::DrawToContext(CGContextRef context, int x, int y, @@ -253,6 +247,18 @@ void BitmapPlatformDeviceMac::DrawToContext(CGContextRef context, int x, int y, if (created_dc) data_->ReleaseBitmapContext(); } + +// Returns the color value at the specified location. +SkColor BitmapPlatformDeviceMac::getColorAt(int x, int y) { + const SkBitmap& bitmap = accessBitmap(true); + SkAutoLockPixels lock(bitmap); + uint32_t* data = bitmap.getAddr32(0, 0); + return static_cast<SkColor>(data[x + y * width()]); +} + +void BitmapPlatformDeviceMac::onAccessBitmap(SkBitmap*) { + // Not needed in CoreGraphics +} void BitmapPlatformDeviceMac::processPixels(int x, int y, int width, int height, @@ -276,17 +282,5 @@ void BitmapPlatformDeviceMac::processPixels(int x, int y, } } -// Returns the color value at the specified location. -SkColor BitmapPlatformDeviceMac::GetColorAt(int x, int y) { - const SkBitmap& bitmap = accessBitmap(true); - SkAutoLockPixels lock(bitmap); - uint32_t* data = bitmap.getAddr32(0, 0); - return static_cast<SkColor>(data[x + y * width()]); -} - -void BitmapPlatformDeviceMac::onAccessBitmap(SkBitmap*) { - // Not needed in CoreGraphics -} - } // namespace gfx diff --git a/base/gfx/bitmap_platform_device_mac.h b/base/gfx/bitmap_platform_device_mac.h index fdbe2e4..a008444 100755 --- a/base/gfx/bitmap_platform_device_mac.h +++ b/base/gfx/bitmap_platform_device_mac.h @@ -56,10 +56,7 @@ class BitmapPlatformDeviceMac : public PlatformDeviceMac { BitmapPlatformDeviceMac& operator=(const BitmapPlatformDeviceMac& other); virtual CGContextRef GetBitmapContext(); - virtual void SetTransform(const SkMatrix& matrix); - - // This currently only supports extremely simple clip rects. - virtual void SetClipRegion(const SkRegion& region); + virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region); virtual void DrawToContext(CGContextRef context, int x, int y, const CGRect* src_rect); @@ -68,7 +65,7 @@ class BitmapPlatformDeviceMac : public PlatformDeviceMac { // Returns the color value at the specified location. This does not // consider any transforms that may be set on the device. - SkColor GetColorAt(int x, int y); + SkColor getColorAt(int x, int y); protected: // Reference counted data that can be shared between multiple devices. This diff --git a/base/gfx/platform_canvas_mac.cc b/base/gfx/platform_canvas_mac.cc index ef06e0e..102655c 100755 --- a/base/gfx/platform_canvas_mac.cc +++ b/base/gfx/platform_canvas_mac.cc @@ -52,81 +52,10 @@ PlatformDeviceMac& PlatformCanvasMac::getTopPlatformDevice() const { return *static_cast<PlatformDeviceMac*>(iter.device()); } -// Clipping ------------------------------------------------------------------- - -bool PlatformCanvasMac::clipRect(const SkRect& rect, SkRegion::Op op) { - bool ret = SkCanvas::clipRect(rect, op); - getTopPlatformDevice().SetClipRegion(getTotalClip()); - return ret; -} - -bool PlatformCanvasMac::clipPath(const SkPath& path, SkRegion::Op op) { - bool ret = SkCanvas::clipPath(path, op); - getTopPlatformDevice().SetClipRegion(getTotalClip()); - return ret; -} - -bool PlatformCanvasMac::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { - bool ret = SkCanvas::clipRegion(deviceRgn, op); - getTopPlatformDevice().SetClipRegion(getTotalClip()); - return ret; -} - -// Transforming --------------------------------------------------------------- - -bool PlatformCanvasMac::translate(SkScalar dx, SkScalar dy) { - if (!SkCanvas::translate(dx, dy)) - return false; - getTopPlatformDevice().SetTransform(getTotalMatrix()); - return true; -} - -bool PlatformCanvasMac::scale(SkScalar sx, SkScalar sy) { - if (!SkCanvas::scale(sx, sy)) - return false; - getTopPlatformDevice().SetTransform(getTotalMatrix()); - return true; -} - -int PlatformCanvasMac::saveLayer(const SkRect* bounds, - const SkPaint* paint, - SaveFlags flags) { - int result = SkCanvas::saveLayer(bounds, paint, flags); - - // saveLayer will have created a new device which, depending on the clip - // rect, may be smaller than the original layer. Therefore, it will have a - // transform applied, and we need to sync CG with that transform. - SkCanvas::LayerIter iter(this, false); - PlatformDeviceMac& new_device = - *static_cast<PlatformDeviceMac*>(iter.device()); - - // There man not actually be a new layer if the layer is empty. - if (!iter.done()) { - new_device.SetTransform(getTotalMatrix()); - new_device.SetClipRegion(getTotalClip()); - } - return result; -} - -int PlatformCanvasMac::save(SkCanvas::SaveFlags flags) { - int ret = SkCanvas::save(flags); - PlatformDeviceMac& device = getTopPlatformDevice(); - device.SetTransform(getTotalMatrix()); - device.SetClipRegion(getTotalClip()); - return ret; -} - -void PlatformCanvasMac::restore() { - SkCanvas::restore(); - PlatformDeviceMac& device = getTopPlatformDevice(); - device.SetTransform(getTotalMatrix()); - device.SetClipRegion(getTotalClip()); -} - SkDevice* PlatformCanvasMac::createDevice(SkBitmap::Config config, int width, int height, - bool is_opaque) { + bool is_opaque, bool isForLayer) { DCHECK(config == SkBitmap::kARGB_8888_Config); return createPlatformDevice(width, height, is_opaque, NULL); } diff --git a/base/gfx/platform_canvas_mac.h b/base/gfx/platform_canvas_mac.h index 3cf2d5a..562b1a0 100755 --- a/base/gfx/platform_canvas_mac.h +++ b/base/gfx/platform_canvas_mac.h @@ -30,15 +30,6 @@ class PlatformCanvasMac : public SkCanvas { // For two-part init, call if you use the no-argument constructor above void initialize(int width, int height, bool is_opaque, CGContextRef context); - // Keep the platform clipping in sync with the skia clipping. Note that - // platform clipping may only clip to the bounds of the clipping region, if - // it is complex. - virtual bool clipRect(const SkRect& rect, - SkRegion::Op op = SkRegion::kIntersect_Op); - virtual bool clipPath(const SkPath& path, - SkRegion::Op op = SkRegion::kIntersect_Op); - virtual bool clipRegion(const SkRegion& deviceRgn, - SkRegion::Op op = SkRegion::kIntersect_Op); // These calls should surround calls to platform drawing routines. The CG // context returned by beginPlatformPaint is the one that can be used to @@ -48,14 +39,6 @@ class PlatformCanvasMac : public SkCanvas { virtual CGContextRef beginPlatformPaint(); virtual void endPlatformPaint(); - // overridden to keep the platform graphics context in sync with the canvas - virtual bool translate(SkScalar dx, SkScalar dy); - virtual bool scale(SkScalar sx, SkScalar sy); - virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, - SaveFlags flags = kARGB_ClipLayer_SaveFlag); - virtual int save(SkCanvas::SaveFlags flags = SkCanvas::kMatrixClip_SaveFlag); - virtual void restore(); - // Returns the platform device pointer of the topmost rect with a non-empty // clip. In practice, this is usually either the top layer or nothing, since // we usually set the clip to new layers when we make them. @@ -80,7 +63,7 @@ class PlatformCanvasMac : public SkCanvas { // the device is always our own so we know that we can use GDI operations // on it. Simply calls into createPlatformDevice(). virtual SkDevice* createDevice(SkBitmap::Config, int width, int height, - bool is_opaque); + bool is_opaque, bool isForLayer); // Creates a device store for use by the canvas. By default, it creates a // BitmapPlatformDevice object. Can be overridden to change the object type. diff --git a/base/gfx/platform_device_mac.cc b/base/gfx/platform_device_mac.cc index 9185dae..ab0b188 100755 --- a/base/gfx/platform_device_mac.cc +++ b/base/gfx/platform_device_mac.cc @@ -97,10 +97,73 @@ void PlatformDeviceMac::LoadPathToCGContext(CGContextRef context, // static void PlatformDeviceMac::LoadTransformToCGContext(CGContextRef context, const SkMatrix& matrix) { - // TOOD: CoreGraphics can concatenate transforms, but not reset the current - // ont. Either find a workaround or remove this function if it turns out + // TODO: CoreGraphics can concatenate transforms, but not reset the current + // one. Either find a workaround or remove this function if it turns out // to be unneeded on the Mac. + // For now, just load the translation. + + // First reset the Transforms. + // TODO(playmobil): no need to call CGContextTranslateCTM() twice + // just add up the numbers and call through. + CGAffineTransform orig_transform = CGContextGetCTM(context); + CGContextTranslateCTM(context, + -orig_transform.tx, + orig_transform.ty); // y axis is flipped. + + // TODO(playmobil): remove debug code. + // CGAffineTransform temp_transform = CGContextGetCTM(context); + + // Now set the new transform. + int tx = matrix.getTranslateX(); + int ty = -matrix.getTranslateY(); + int height = CGBitmapContextGetHeight(context); + CGContextTranslateCTM(context, + tx, + -(ty+height)); + CGAffineTransform new_transform = CGContextGetCTM(context); +// TODO(playmobil): remove debug code. +// printf("tx_matrix (%lf,%lf)->(%lf,%lf)->(%lf,%lf) (%d, %d) height=%d\n", orig_transform.tx, +// orig_transform.ty, +// foo_transform.tx, +// foo_transform.ty, +// new_transform.tx, +// new_transform.ty, tx, ty, height); } +// static +void PlatformDeviceMac::LoadClippingRegionToCGContext( + CGContextRef context, + const SkRegion& region, + const SkMatrix& transformation) { + if (region.isEmpty()) { + // region can be empty, in which case everything will be clipped. + SkRect rect; + rect.setEmpty(); + CGContextClipToRect(context, SkRectToCGRect(rect)); + } else if (region.isRect()) { + // Do the transformation. + SkRect rect; + rect.set(region.getBounds()); + transformation.mapRect(&rect); + SkIRect irect; + rect.round(&irect); +// TODO(playmobil): remove debug code. +// printf("Clipping to (%d,%d) (%d,%d)\n", irect.fLeft, irect.fTop, +// irect.fRight, irect.fBottom); + CGContextClipToRect(context, SkIRectToCGRect(irect)); + } else { + // It is complex. + SkPath path; + region.getBoundaryPath(&path); + // Clip. Note that windows clipping regions are not affected by the + // transform so apply it manually. + path.transform(transformation); + // TODO(playmobil): Implement. + NOTREACHED(); + // LoadPathToDC(context, path); + // hrgn = PathToRegion(context); + } +} + } // namespace gfx diff --git a/base/gfx/platform_device_mac.h b/base/gfx/platform_device_mac.h index 590cd24..79a14be 100755 --- a/base/gfx/platform_device_mac.h +++ b/base/gfx/platform_device_mac.h @@ -27,13 +27,6 @@ class PlatformDeviceMac : public SkDevice { // should exist only during one pass of rendering. virtual CGContextRef GetBitmapContext() = 0; - // Translate the device's coordinate system by the given amount; this will - // override any previous calls to this function. - virtual void SetTransform(const SkMatrix& matrix) = 0; - - // Sets the clipping region, overriding any previous calls. - virtual void SetClipRegion(const SkRegion& region) = 0; - // Draws to the given graphics context. If the bitmap context doesn't exist, // this will temporarily create it. However, if you have created the bitmap // context, it will be more efficient if you don't free it until after this @@ -61,6 +54,11 @@ class PlatformDeviceMac : public SkDevice { // clipping or as a stroke. static void LoadPathToCGContext(CGContextRef context, const SkPath& path); + // Loads a SkRegion into the CG context. + static void LoadClippingRegionToCGContext(CGContextRef context, + const SkRegion& region, + const SkMatrix& transformation); + protected: // Forwards |bitmap| to SkDevice's constructor. PlatformDeviceMac(const SkBitmap& bitmap); |