summaryrefslogtreecommitdiffstats
path: root/skia/ext
diff options
context:
space:
mode:
Diffstat (limited to 'skia/ext')
-rw-r--r--skia/ext/skia_utils_mac.h4
-rw-r--r--skia/ext/skia_utils_mac.mm33
-rw-r--r--skia/ext/skia_utils_mac_unittest.mm50
3 files changed, 70 insertions, 17 deletions
diff --git a/skia/ext/skia_utils_mac.h b/skia/ext/skia_utils_mac.h
index efa98c0..da290ea 100644
--- a/skia/ext/skia_utils_mac.h
+++ b/skia/ext/skia_utils_mac.h
@@ -9,12 +9,12 @@
#include <ApplicationServices/ApplicationServices.h>
#include <vector>
+#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
struct SkIRect;
struct SkPoint;
struct SkRect;
-class SkBitmap;
class SkCanvas;
class SkMatrix;
#ifdef __LP64__
@@ -108,6 +108,8 @@ class SK_API SkiaBitLocker {
void releaseIfNeeded();
SkCanvas* canvas_;
CGContextRef cgContext_;
+ SkBitmap bitmap_;
+ bool useDeviceBits_;
};
diff --git a/skia/ext/skia_utils_mac.mm b/skia/ext/skia_utils_mac.mm
index b227355..f359089 100644
--- a/skia/ext/skia_utils_mac.mm
+++ b/skia/ext/skia_utils_mac.mm
@@ -318,10 +318,15 @@ SkiaBitLocker::~SkiaBitLocker() {
releaseIfNeeded();
}
+// This must be called to balance calls to cgContext
void SkiaBitLocker::releaseIfNeeded() {
if (!cgContext_)
return;
- canvas_->getTopDevice()->accessBitmap(true).unlockPixels();
+ if (useDeviceBits_) {
+ bitmap_.unlockPixels();
+ } else {
+ canvas_->drawBitmap(bitmap_, 0, 0);
+ }
CGContextRelease(cgContext_);
cgContext_ = 0;
}
@@ -331,12 +336,20 @@ CGContextRef SkiaBitLocker::cgContext() {
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(),
+ releaseIfNeeded(); // This flushes any prior bitmap use
+ const SkBitmap& deviceBits = device->accessBitmap(true);
+ useDeviceBits_ = deviceBits.getPixels();
+ if (useDeviceBits_) {
+ bitmap_ = deviceBits;
+ bitmap_.lockPixels();
+ } else {
+ bitmap_.setConfig(
+ SkBitmap::kARGB_8888_Config, deviceBits.width(), deviceBits.height());
+ bitmap_.allocPixels();
+ bitmap_.eraseColor(0);
+ }
+ cgContext_ = CGBitmapContextCreate(bitmap_.getPixels(), bitmap_.width(),
+ bitmap_.height(), 8, bitmap_.rowBytes(), CGColorSpaceCreateDeviceRGB(),
kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);
// Apply device matrix.
@@ -345,6 +358,12 @@ CGContextRef SkiaBitLocker::cgContext() {
-device->height());
CGContextConcatCTM(cgContext_, contentsTransform);
+ // Skip applying the matrix and clip when not writing directly to device.
+ // They're applied in the offscreen case when the bitmap is drawn.
+ if (!useDeviceBits_) {
+ return cgContext_;
+ }
+
// Apply clip in device coordinates.
CGMutablePathRef clipPath = CGPathCreateMutable();
const SkRegion& clipRgn = canvas_->getTotalClip();
diff --git a/skia/ext/skia_utils_mac_unittest.mm b/skia/ext/skia_utils_mac_unittest.mm
index b2175cd..24310b0 100644
--- a/skia/ext/skia_utils_mac_unittest.mm
+++ b/skia/ext/skia_utils_mac_unittest.mm
@@ -25,7 +25,11 @@ class SkiaUtilsMacTest : public testing::Test {
TestIdentity = 0,
TestTranslate = 1,
TestClip = 2,
- TestXClip = TestTranslate | TestClip
+ TestXClip = TestTranslate | TestClip,
+ TestNoBits = 4,
+ TestTranslateNoBits = TestTranslate | TestNoBits,
+ TestClipNoBits = TestClip | TestNoBits,
+ TestXClipNoBits = TestXClip | TestNoBits,
};
void RunBitLockerTest(BitLockerTest test);
@@ -119,7 +123,9 @@ void SkiaUtilsMacTest::RunBitLockerTest(BitLockerTest test) {
memcpy(bits, original, sizeof(original));
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bitmap.setPixels(bits);
+ if (!(test & TestNoBits)) {
+ bitmap.setPixels(bits);
+ }
SkCanvas canvas;
canvas.setBitmapDevice(bitmap);
if (test & TestTranslate)
@@ -128,12 +134,22 @@ void SkiaUtilsMacTest::RunBitLockerTest(BitLockerTest test) {
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);
+ {
+ gfx::SkiaBitLocker bitLocker(&canvas);
+ CGContextRef cgContext = bitLocker.cgContext();
+ CGColorRef testColor = CGColorGetConstantColor(kCGColorWhite);
+ CGContextSetFillColorWithColor(cgContext, testColor);
+ CGRect cgRect = {{0, 0}, {width, height}};
+ CGContextFillRect(cgContext, cgRect);
+ if (test & TestNoBits) {
+ bitmap.setPixels(bits);
+ canvas.setBitmapDevice(bitmap);
+ if (test & TestClip) {
+ SkRect clipRect = {0, height / 2, width, height};
+ canvas.clipRect(clipRect);
+ }
+ }
+ }
const unsigned results[][storageSize] = {
{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, // identity
{0xFF333333, 0xFFFFFFFF, 0xFF999999, 0xFFFFFFFF}, // translate
@@ -141,7 +157,7 @@ void SkiaUtilsMacTest::RunBitLockerTest(BitLockerTest test) {
{0xFF333333, 0xFF666666, 0xFF999999, 0xFFFFFFFF} // translate | clip
};
for (unsigned index = 0; index < storageSize; index++)
- EXPECT_EQ(results[test][index], bits[index]);
+ EXPECT_EQ(results[test & ~TestNoBits][index], bits[index]);
}
void SkiaUtilsMacTest::ShapeHelper(int width, int height,
@@ -231,5 +247,21 @@ TEST_F(SkiaUtilsMacTest, BitLocker_XClip) {
RunBitLockerTest(SkiaUtilsMacTest::TestXClip);
}
+TEST_F(SkiaUtilsMacTest, BitLocker_NoBits) {
+ RunBitLockerTest(SkiaUtilsMacTest::TestNoBits);
+}
+
+TEST_F(SkiaUtilsMacTest, BitLocker_TranslateNoBits) {
+ RunBitLockerTest(SkiaUtilsMacTest::TestTranslateNoBits);
+}
+
+TEST_F(SkiaUtilsMacTest, BitLocker_ClipNoBits) {
+ RunBitLockerTest(SkiaUtilsMacTest::TestClipNoBits);
+}
+
+TEST_F(SkiaUtilsMacTest, BitLocker_XClipNoBits) {
+ RunBitLockerTest(SkiaUtilsMacTest::TestXClipNoBits);
+}
+
} // namespace