diff options
author | caryclark@chromium.org <caryclark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-17 23:06:11 +0000 |
---|---|---|
committer | caryclark@chromium.org <caryclark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-17 23:06:11 +0000 |
commit | 02c48b0f977407888733ceb5f855a0195ec6f2ba (patch) | |
tree | f558b24c1c2b3a3514beebf45eb25494cc05486f /skia | |
parent | 73a516a76cd236c32d67b8f558a4aabc601e3481 (diff) | |
download | chromium_src-02c48b0f977407888733ceb5f855a0195ec6f2ba.zip chromium_src-02c48b0f977407888733ceb5f855a0195ec6f2ba.tar.gz chromium_src-02c48b0f977407888733ceb5f855a0195ec6f2ba.tar.bz2 |
Add utility for converting SkCanvas to CGContext
Skia on Mac uses Skia to render WebKit, and CG
to render UI elements. The CG elements need a
transcribed graphics context that preserves the
canvas matrix, and the canvas clip.
The BitLockerSkia utility class sets up a CGContext
from the SkCanvas, locks the bitmap's bits, and
releases the lock when the class goes out of scope.
Each time the CGContext is retrieved, it is rebuilt.
This permits the caller to modify the same canvas
between calls.
Outside of the unit test, there are no callers
to this utility for now.
BUG=79463
TEST=SkiaUtilsMacTest.*
Review URL: http://codereview.chromium.org/7031006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85692 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia')
-rw-r--r-- | skia/ext/skia_utils_mac.h | 17 | ||||
-rw-r--r-- | skia/ext/skia_utils_mac.mm | 59 | ||||
-rw-r--r-- | skia/ext/skia_utils_mac_unittest.mm | 62 |
3 files changed, 136 insertions, 2 deletions
diff --git a/skia/ext/skia_utils_mac.h b/skia/ext/skia_utils_mac.h index 04d4a1d..fb9a66d 100644 --- a/skia/ext/skia_utils_mac.h +++ b/skia/ext/skia_utils_mac.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -15,6 +15,7 @@ struct SkIRect; struct SkPoint; struct SkRect; class SkBitmap; +class SkCanvas; class SkMatrix; #ifdef __LP64__ typedef CGSize NSSize; @@ -86,6 +87,20 @@ NSImage* SkBitmapsToNSImage(const std::vector<const SkBitmap*>& bitmaps); // Returns |[NSImage imageNamed:@"NSApplicationIcon"]| as SkBitmap. SkBitmap AppplicationIconAtSize(int size); +// Converts a SkCanvas temporarily to a CGContext +class SkiaBitLocker { + public: + explicit SkiaBitLocker(SkCanvas* canvas); + ~SkiaBitLocker(); + CGContextRef cgContext(); + + private: + void releaseIfNeeded(); + SkCanvas* canvas_; + CGContextRef cgContext_; +}; + + } // namespace gfx #endif // SKIA_EXT_SKIA_UTILS_MAC_H_ diff --git a/skia/ext/skia_utils_mac.mm b/skia/ext/skia_utils_mac.mm index 5547c4a..ecb30ca 100644 --- a/skia/ext/skia_utils_mac.mm +++ b/skia/ext/skia_utils_mac.mm @@ -7,10 +7,12 @@ #import <AppKit/AppKit.h> #include "base/logging.h" +#include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/memory/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" #include "skia/ext/bitmap_platform_device_mac.h" +#include "third_party/skia/include/core/SkRegion.h" #include "third_party/skia/include/utils/mac/SkCGUtils.h" #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" @@ -284,4 +286,61 @@ SkBitmap AppplicationIconAtSize(int size) { return NSImageToSkBitmap(image, NSMakeSize(size, size), /* is_opaque=*/true); } + +SkiaBitLocker::SkiaBitLocker(SkCanvas* canvas) + : canvas_(canvas), + cgContext_(0) { +} + +SkiaBitLocker::~SkiaBitLocker() { + releaseIfNeeded(); +} + +void SkiaBitLocker::releaseIfNeeded() { + if (!cgContext_) + return; + canvas_->getDevice()->accessBitmap(true).unlockPixels(); + CGContextRelease(cgContext_); + cgContext_ = 0; +} + +CGContextRef SkiaBitLocker::cgContext() { + SkDevice* device = canvas_->getDevice(); + DCHECK(device); + if (!device) + return 0; + releaseIfNeeded(); + const SkBitmap& bitmap = device->accessBitmap(true); + bitmap.lockPixels(); + void* pixels = bitmap.getPixels(); + cgContext_ = CGBitmapContextCreate(pixels, device->width(), + device->height(), 8, bitmap.rowBytes(), CGColorSpaceCreateDeviceRGB(), + kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst); + + // Apply device matrix. + CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1); + contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, + -device->height()); + CGContextConcatCTM(cgContext_, contentsTransform); + + // Apply clip in device coordinates. + CGMutablePathRef clipPath = CGPathCreateMutable(); + SkRegion::Iterator iter(canvas_->getTotalClip()); + for (; !iter.done(); iter.next()) { + const SkIRect& skRect = iter.rect(); + CGRect cgRect = SkIRectToCGRect(skRect); + CGPathAddRect(clipPath, 0, cgRect); + } + CGContextAddPath(cgContext_, clipPath); + CGContextClip(cgContext_); + CGPathRelease(clipPath); + + // Apply content matrix. + const SkMatrix& skMatrix = canvas_->getTotalMatrix(); + CGAffineTransform affine = SkMatrixToCGAffineTransform(skMatrix); + CGContextConcatCTM(cgContext_, affine); + + return cgContext_; +} + } // namespace gfx diff --git a/skia/ext/skia_utils_mac_unittest.mm b/skia/ext/skia_utils_mac_unittest.mm index 132c6ac..b2175cd 100644 --- a/skia/ext/skia_utils_mac_unittest.mm +++ b/skia/ext/skia_utils_mac_unittest.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -21,6 +21,14 @@ class SkiaUtilsMacTest : public testing::Test { // Checks that the given bitmap is actually red or blue. void TestSkBitmap(const SkBitmap& bitmap, bool isred); + enum BitLockerTest { + TestIdentity = 0, + TestTranslate = 1, + TestClip = 2, + TestXClip = TestTranslate | TestClip + }; + void RunBitLockerTest(BitLockerTest test); + // If not red, is blue. // If not tfbit (twenty-four-bit), is 444. void ShapeHelper(int width, int height, bool isred, bool tfbit); @@ -101,6 +109,41 @@ void SkiaUtilsMacTest::TestSkBitmap(const SkBitmap& bitmap, bool isred) { EXPECT_GT(SkColorGetA(color), 245u); } +void SkiaUtilsMacTest::RunBitLockerTest(BitLockerTest test) { + const unsigned width = 2; + const unsigned height = 2; + const unsigned storageSize = width * height; + const unsigned original[] = {0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC}; + EXPECT_EQ(storageSize, sizeof(original) / sizeof(original[0])); + unsigned bits[storageSize]; + memcpy(bits, original, sizeof(original)); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); + bitmap.setPixels(bits); + SkCanvas canvas; + canvas.setBitmapDevice(bitmap); + if (test & TestTranslate) + canvas.translate(width / 2, 0); + if (test & TestClip) { + SkRect clipRect = {0, height / 2, width, height}; + canvas.clipRect(clipRect); + } + gfx::SkiaBitLocker bitLocker(&canvas); + CGContextRef cgContext = bitLocker.cgContext(); + CGColorRef testColor = CGColorGetConstantColor(kCGColorWhite); + CGContextSetFillColorWithColor(cgContext, testColor); + CGRect cgRect = {{0, 0}, {width, height}}; + CGContextFillRect(cgContext, cgRect); + const unsigned results[][storageSize] = { + {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, // identity + {0xFF333333, 0xFFFFFFFF, 0xFF999999, 0xFFFFFFFF}, // translate + {0xFF333333, 0xFF666666, 0xFFFFFFFF, 0xFFFFFFFF}, // clip + {0xFF333333, 0xFF666666, 0xFF999999, 0xFFFFFFFF} // translate | clip + }; + for (unsigned index = 0; index < storageSize; index++) + EXPECT_EQ(results[test][index], bits[index]); +} + void SkiaUtilsMacTest::ShapeHelper(int width, int height, bool isred, bool tfbit) { SkBitmap thing(CreateSkBitmap(width, height, isred, tfbit)); @@ -172,4 +215,21 @@ TEST_F(SkiaUtilsMacTest, NSImageRepToSkBitmap) { TestSkBitmap(bitmap, isred); } +TEST_F(SkiaUtilsMacTest, BitLocker_Identity) { + RunBitLockerTest(SkiaUtilsMacTest::TestIdentity); +} + +TEST_F(SkiaUtilsMacTest, BitLocker_Translate) { + RunBitLockerTest(SkiaUtilsMacTest::TestTranslate); +} + +TEST_F(SkiaUtilsMacTest, BitLocker_Clip) { + RunBitLockerTest(SkiaUtilsMacTest::TestClip); +} + +TEST_F(SkiaUtilsMacTest, BitLocker_XClip) { + RunBitLockerTest(SkiaUtilsMacTest::TestXClip); +} + } // namespace + |