diff options
-rw-r--r-- | include/core/SkCanvas.h | 29 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 40 | ||||
-rw-r--r-- | tests/CanvasTest.cpp | 42 | ||||
-rw-r--r-- | tests/DrawPathTest.cpp | 19 |
4 files changed, 115 insertions, 15 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 8cc8bc9eb7..b73a1e48ca 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -49,6 +49,35 @@ public: SK_DECLARE_INST_COUNT(SkCanvas) /** + * Attempt to allocate an offscreen raster canvas, matching the ImageInfo. + * On success, return a new canvas that will draw into that offscreen. + * + * The caller can access the pixels after drawing into this canvas by + * calling readPixels() or peekPixels(). + * + * If the requested ImageInfo is opaque (either the colortype is + * intrinsically opaque like RGB_565, or the info's alphatype is kOpaque) + * then the pixel memory may be uninitialized. Otherwise, the pixel memory + * will be initialized to 0, which is interpreted as transparent. + * + * On failure, return NULL. This can fail for several reasons: + * 1. the memory allocation failed (e.g. request is too large) + * 2. invalid ImageInfo (e.g. negative dimensions) + * 3. unsupported ImageInfo for a canvas + * - kUnknown_SkColorType, kIndex_8_SkColorType + * - kIgnore_SkAlphaType + * - this list is not complete, so others may also be unsupported + * + * Note: it is valid to request a supported ImageInfo, but with zero + * dimensions. + */ + static SkCanvas* NewRaster(const SkImageInfo&); + + static SkCanvas* NewRasterN32(int width, int height) { + return NewRaster(SkImageInfo::MakeN32Premul(width, height)); + } + + /** * Creates an empty canvas with no backing device/pixels, and zero * dimensions. */ diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index a67891e659..bc14974b7d 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -2314,3 +2314,43 @@ int SkCanvas::LayerIter::y() const { return fImpl->getY(); } /////////////////////////////////////////////////////////////////////////////// SkCanvas::ClipVisitor::~ClipVisitor() { } + +/////////////////////////////////////////////////////////////////////////////// + +static bool supported_for_raster_canvas(const SkImageInfo& info) { + switch (info.alphaType()) { + case kPremul_SkAlphaType: + case kOpaque_SkAlphaType: + break; + default: + return false; + } + + switch (info.colorType()) { + case kAlpha_8_SkColorType: + case kRGB_565_SkColorType: + case kPMColor_SkColorType: + break; + default: + return false; + } + + return true; +} + +SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) { + if (!supported_for_raster_canvas(info)) { + return NULL; + } + + SkBitmap bitmap; + if (!bitmap.allocPixels(info)) { + return NULL; + } + + // should this functionality be moved into allocPixels()? + if (!bitmap.info().isOpaque()) { + bitmap.eraseColor(0); + } + return SkNEW_ARGS(SkCanvas, (bitmap)); +} diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp index 5f3d79ceeb..18c683dbc1 100644 --- a/tests/CanvasTest.cpp +++ b/tests/CanvasTest.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2012 Google Inc. * @@ -893,6 +892,45 @@ static void TestOverrideStateConsistency(skiatest::Reporter* reporter, } } +static void test_newraster(skiatest::Reporter* reporter) { + SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); + SkCanvas* canvas = SkCanvas::NewRaster(info); + REPORTER_ASSERT(reporter, canvas); + + SkImageInfo info2; + size_t rowBytes; + const SkPMColor* addr = (const SkPMColor*)canvas->peekPixels(&info2, &rowBytes); + REPORTER_ASSERT(reporter, addr); + REPORTER_ASSERT(reporter, info == info2); + for (int y = 0; y < info.height(); ++y) { + for (int x = 0; x < info.width(); ++x) { + REPORTER_ASSERT(reporter, 0 == addr[x]); + } + addr = (const SkPMColor*)((const char*)addr + rowBytes); + } + SkDELETE(canvas); + + // now try a deliberately bad info + info.fWidth = -1; + REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); + + // too big + info.fWidth = 1 << 30; + info.fHeight = 1 << 30; + REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); + + // not a valid pixel type + info.fWidth = info.fHeight = 10; + info.fColorType = kUnknown_SkColorType; + REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); + + // We should succeed with a zero-sized valid info + info = SkImageInfo::MakeN32Premul(0, 0); + canvas = SkCanvas::NewRaster(info); + REPORTER_ASSERT(reporter, canvas); + SkDELETE(canvas); +} + DEF_TEST(Canvas, reporter) { // Init global here because bitmap pixels cannot be alocated during // static initialization @@ -909,4 +947,6 @@ DEF_TEST(Canvas, reporter) { // Explicitly call reset(), so we don't leak the pixels (since kTestBitmap is a global) kTestBitmap.reset(); + + test_newraster(reporter); } diff --git a/tests/DrawPathTest.cpp b/tests/DrawPathTest.cpp index f7f7367983..fafef02a52 100644 --- a/tests/DrawPathTest.cpp +++ b/tests/DrawPathTest.cpp @@ -11,14 +11,6 @@ #include "SkSurface.h" #include "Test.h" -static SkCanvas* new_canvas(int w, int h) { - SkBitmap bm; - bm.allocN32Pixels(w, h); - return new SkCanvas(bm); -} - -/////////////////////////////////////////////////////////////////////////////// - // test that we can draw an aa-rect at coordinates > 32K (bigger than fixedpoint) static void test_big_aa_rect(skiatest::Reporter* reporter) { SkBitmap output; @@ -103,7 +95,7 @@ static void test_crbug131181() { moveToH(&path, &data[0]); cubicToH(&path, &data[2]); - SkAutoTUnref<SkCanvas> canvas(new_canvas(640, 480)); + SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(640, 480)); SkPaint paint; paint.setAntiAlias(true); @@ -141,7 +133,7 @@ static void test_inversepathwithclip() { SkPaint paint; - SkAutoTUnref<SkCanvas> canvas(new_canvas(640, 480)); + SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(640, 480)); canvas.get()->save(); canvas.get()->clipRect(SkRect::MakeWH(SkIntToScalar(19), SkIntToScalar(11))); @@ -181,7 +173,7 @@ static void test_bug533() { SkPaint paint; paint.setAntiAlias(true); - SkAutoTUnref<SkCanvas> canvas(new_canvas(640, 480)); + SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(640, 480)); canvas.get()->drawPath(path, paint); } @@ -223,7 +215,7 @@ static void test_bigcubic() { SkPaint paint; paint.setAntiAlias(true); - SkAutoTUnref<SkCanvas> canvas(new_canvas(640, 480)); + SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(640, 480)); canvas.get()->drawPath(path, paint); } @@ -233,8 +225,7 @@ static void test_bigcubic() { static void test_giantaa() { const int W = 400; const int H = 400; - SkAutoTUnref<SkCanvas> canvas(new_canvas(33000, 10)); - canvas.get()->clear(SK_ColorTRANSPARENT); + SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(33000, 10)); SkPaint paint; paint.setAntiAlias(true); |