diff options
Diffstat (limited to 'skia/ext')
-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 + |