summaryrefslogtreecommitdiffstats
path: root/skia/ext
diff options
context:
space:
mode:
Diffstat (limited to 'skia/ext')
-rw-r--r--skia/ext/skia_utils_mac.h17
-rw-r--r--skia/ext/skia_utils_mac.mm59
-rw-r--r--skia/ext/skia_utils_mac_unittest.mm62
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
+