summaryrefslogtreecommitdiffstats
path: root/skia/ext
diff options
context:
space:
mode:
authorcaryclark@google.com <caryclark@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-11 17:37:17 +0000
committercaryclark@google.com <caryclark@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-11 17:37:17 +0000
commitb8c84c061a245ee966bb42d5e7942560688910db (patch)
tree7dc6a96937d72e2ecfa0600a5787ed67b236d75e /skia/ext
parente18b9c2762c2a863e3737a75647500b252d143d1 (diff)
downloadchromium_src-b8c84c061a245ee966bb42d5e7942560688910db.zip
chromium_src-b8c84c061a245ee966bb42d5e7942560688910db.tar.gz
chromium_src-b8c84c061a245ee966bb42d5e7942560688910db.tar.bz2
Create a local bitmap to capture CoreGraphics rendering
when the canvas is not backed by a bitmap. During normal desktop drawing, CoreGraphics calls that image theme elements like checkboxes and buttons draw into the device bitmap owned by Skia's canvas. When a PDF is created as part of a print preview, no bitmap is allocated. In the latter case, associate a local array of pixels with the CGContext to capture the theme rendering, then draw it with Skia once the theme rendering is complete. This fix over-allocates memory. It creates a pixel map as large as the device. The bounds of the CG drawing is not visible to Skia, and the clip may not be set. The PDF may be larger than need be for the same reason. In a subsequent change, the theme element's bounds can reduce the size of the bitmap allocation. This could be done by setting the clip or by passing the rectangle to the graphics context. This would require a sizeable edit to RenderThemeMac.mm. Also, change the unit test to test both paths, when the device is backed by a bitmap, and when it is not. This requires the unit test to call the destructor and reset the clip before comparing the results. BUG=121752 TEST=http://stmarksparish.com/printtest.aspx, print to PDF TEST=SkiaUtilsMacTest.BitLocker_* Review URL: https://chromiumcodereview.appspot.com/10031005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131795 0039d316-1c4b-4281-b951-d872f2087c98
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