summaryrefslogtreecommitdiffstats
path: root/skia
diff options
context:
space:
mode:
authorcaryclark@chromium.org <caryclark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-17 23:06:11 +0000
committercaryclark@chromium.org <caryclark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-17 23:06:11 +0000
commit02c48b0f977407888733ceb5f855a0195ec6f2ba (patch)
treef558b24c1c2b3a3514beebf45eb25494cc05486f /skia
parent73a516a76cd236c32d67b8f558a4aabc601e3481 (diff)
downloadchromium_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.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
+