diff options
Diffstat (limited to 'skia/ext')
-rw-r--r-- | skia/ext/skia_utils_mac.h | 4 | ||||
-rw-r--r-- | skia/ext/skia_utils_mac.mm | 33 | ||||
-rw-r--r-- | skia/ext/skia_utils_mac_unittest.mm | 50 |
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 |