diff options
-rw-r--r-- | gm/bitmapsource.cpp | 95 | ||||
-rw-r--r-- | gm/tileimagefilter.cpp | 5 | ||||
-rw-r--r-- | gm/xfermodeimagefilter.cpp | 44 | ||||
-rw-r--r-- | gyp/gmslides.gypi | 1 | ||||
-rw-r--r-- | include/effects/SkBitmapSource.h | 2 | ||||
-rw-r--r-- | src/effects/SkBitmapSource.cpp | 53 |
6 files changed, 170 insertions, 30 deletions
diff --git a/gm/bitmapsource.cpp b/gm/bitmapsource.cpp new file mode 100644 index 0000000000..f3507eb18d --- /dev/null +++ b/gm/bitmapsource.cpp @@ -0,0 +1,95 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" + +#include "SkBitmapSource.h" + +class BitmapSourceGM : public skiagm::GM { +public: + BitmapSourceGM() : fInitialized(false) { + } + +protected: + virtual SkString onShortName() { + return SkString("bitmapsource"); + } + + void make_bitmap() { + fBitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); + fBitmap.allocPixels(); + SkBitmapDevice device(fBitmap); + SkCanvas canvas(&device); + canvas.clear(0x00000000); + SkPaint paint; + paint.setAntiAlias(true); + paint.setColor(0xFFFFFFFF); + paint.setTextSize(SkIntToScalar(96)); + const char* str = "e"; + canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint); + } + + virtual SkISize onISize() { return SkISize::Make(500, 150); } + + virtual void onDraw(SkCanvas* canvas) { + if (!fInitialized) { + this->make_bitmap(); + fInitialized = true; + } + canvas->clear(0x00000000); + { + SkRect srcRect = SkRect::MakeXYWH(20, 20, 30, 30); + SkRect dstRect = SkRect::MakeXYWH(0, 10, 60, 60); + SkRect clipRect = SkRect::MakeXYWH(0, 0, 100, 100); + SkRect bounds; + fBitmap.getBounds(&bounds); + SkAutoTUnref<SkImageFilter> bitmapSource(new SkBitmapSource(fBitmap)); + SkAutoTUnref<SkImageFilter> bitmapSourceSrcRect(new SkBitmapSource(fBitmap, srcRect, srcRect)); + SkAutoTUnref<SkImageFilter> bitmapSourceSrcRectDstRect(new SkBitmapSource(fBitmap, srcRect, dstRect)); + SkAutoTUnref<SkImageFilter> bitmapSourceDstRectOnly(new SkBitmapSource(fBitmap, bounds, dstRect)); + + SkPaint paint; + paint.setImageFilter(bitmapSource); + canvas->save(); + canvas->clipRect(clipRect); + canvas->drawPaint(paint); + canvas->restore(); + canvas->translate(SkIntToScalar(100), 0); + + paint.setImageFilter(bitmapSourceSrcRect); + canvas->save(); + canvas->clipRect(clipRect); + canvas->drawPaint(paint); + canvas->restore(); + canvas->translate(SkIntToScalar(100), 0); + + paint.setImageFilter(bitmapSourceSrcRectDstRect); + canvas->save(); + canvas->clipRect(clipRect); + canvas->drawPaint(paint); + canvas->restore(); + canvas->translate(SkIntToScalar(100), 0); + + paint.setImageFilter(bitmapSourceDstRectOnly); + canvas->save(); + canvas->clipRect(clipRect); + canvas->drawPaint(paint); + canvas->restore(); + canvas->translate(SkIntToScalar(100), 0); + } + } + +private: + typedef GM INHERITED; + SkBitmap fBitmap; + bool fInitialized; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static skiagm::GM* MyFactory(void*) { return new BitmapSourceGM; } +static skiagm::GMRegistry reg(MyFactory); diff --git a/gm/tileimagefilter.cpp b/gm/tileimagefilter.cpp index 9a14344772..48d65ca073 100644 --- a/gm/tileimagefilter.cpp +++ b/gm/tileimagefilter.cpp @@ -70,9 +70,10 @@ protected: void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint, SkScalar x, SkScalar y) { canvas->save(); - canvas->clipRect(SkRect::MakeXYWH(x, y, + canvas->translate(x, y); + canvas->clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()))); - canvas->drawBitmap(bitmap, x, y, &paint); + canvas->drawBitmap(bitmap, 0, 0, &paint); canvas->restore(); } diff --git a/gm/xfermodeimagefilter.cpp b/gm/xfermodeimagefilter.cpp index 01bfe0ad61..9d73b8314a 100644 --- a/gm/xfermodeimagefilter.cpp +++ b/gm/xfermodeimagefilter.cpp @@ -72,9 +72,19 @@ protected: void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint, SkScalar x, SkScalar y) { canvas->save(); - canvas->clipRect(SkRect::MakeXYWH(x, y, + canvas->translate(x, y); + canvas->clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()))); - canvas->drawBitmap(bitmap, x, y, &paint); + canvas->drawBitmap(bitmap, 0, 0, &paint); + canvas->restore(); + } + + void drawClippedPaint(SkCanvas* canvas, const SkRect& rect, const SkPaint& paint, + SkScalar x, SkScalar y) { + canvas->save(); + canvas->translate(x, y); + canvas->clipRect(rect); + canvas->drawPaint(paint); canvas->restore(); } @@ -156,6 +166,8 @@ protected: x = 0; y += fBitmap.height() + MARGIN; } + SkRect clipRect = SkRect::MakeWH(SkIntToScalar(fBitmap.width() + 4), + SkIntToScalar(fBitmap.height() + 4)); // Test offsets on SrcMode (uses fixed-function blend) SkAutoTUnref<SkImageFilter> foreground(SkNEW_ARGS(SkBitmapSource, (fBitmap))); SkAutoTUnref<SkImageFilter> offsetForeground(SkNEW_ARGS(SkOffsetImageFilter, @@ -166,13 +178,7 @@ protected: filter.reset(SkNEW_ARGS(SkXfermodeImageFilter, (mode, offsetBackground, offsetForeground))); paint.setImageFilter(filter); - canvas->save(); - canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), - SkIntToScalar(y), - SkIntToScalar(fBitmap.width() + 4), - SkIntToScalar(fBitmap.height() + 4))); - canvas->drawPaint(paint); - canvas->restore(); + drawClippedPaint(canvas, clipRect, paint, x, y); x += fBitmap.width() + MARGIN; if (x + fBitmap.width() > WIDTH) { x = 0; @@ -182,13 +188,7 @@ protected: mode.reset(SkXfermode::Create(SkXfermode::kDarken_Mode)); filter.reset(SkNEW_ARGS(SkXfermodeImageFilter, (mode, offsetBackground, offsetForeground))); paint.setImageFilter(filter); - canvas->save(); - canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), - SkIntToScalar(y), - SkIntToScalar(fBitmap.width() + 4), - SkIntToScalar(fBitmap.height() + 4))); - canvas->drawPaint(paint); - canvas->restore(); + drawClippedPaint(canvas, clipRect, paint, x, y); x += fBitmap.width() + MARGIN; if (x + fBitmap.width() > WIDTH) { x = 0; @@ -203,8 +203,8 @@ protected: { 10, 10, 10, 10}, {-10, -10, -6, -6}}; for (size_t i = 0; i < nbSamples; ++i) { - SkIRect cropRect = SkIRect::MakeXYWH(x + offsets[i][0], - y + offsets[i][1], + SkIRect cropRect = SkIRect::MakeXYWH(offsets[i][0], + offsets[i][1], fBitmap.width() + offsets[i][2], fBitmap.height() + offsets[i][3]); SkImageFilter::CropRect rect(SkRect::Make(cropRect)); @@ -212,13 +212,7 @@ protected: filter.reset(SkNEW_ARGS(SkXfermodeImageFilter, (mode, offsetBackground, offsetForeground, &rect))); paint.setImageFilter(filter); - canvas->save(); - canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), - SkIntToScalar(y), - SkIntToScalar(fBitmap.width() + 4), - SkIntToScalar(fBitmap.height() + 4))); - canvas->drawPaint(paint); - canvas->restore(); + drawClippedPaint(canvas, clipRect, paint, x, y); x += fBitmap.width() + MARGIN; if (x + fBitmap.width() > WIDTH) { x = 0; diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index f8f38e94ff..4dd03ce9de 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -20,6 +20,7 @@ '../gm/bitmaprect.cpp', '../gm/bitmaprecttest.cpp', '../gm/bitmapscroll.cpp', + '../gm/bitmapsource.cpp', '../gm/bleed.cpp', '../gm/blurs.cpp', '../gm/blurquickreject.cpp', diff --git a/include/effects/SkBitmapSource.h b/include/effects/SkBitmapSource.h index 138987e701..699186e9f1 100644 --- a/include/effects/SkBitmapSource.h +++ b/include/effects/SkBitmapSource.h @@ -14,6 +14,7 @@ class SK_API SkBitmapSource : public SkImageFilter { public: explicit SkBitmapSource(const SkBitmap& bitmap); + SkBitmapSource(const SkBitmap& bitmap, const SkRect& srcRect, const SkRect& dstRect); SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBitmapSource) @@ -25,6 +26,7 @@ protected: private: SkBitmap fBitmap; + SkRect fSrcRect, fDstRect; typedef SkImageFilter INHERITED; }; diff --git a/src/effects/SkBitmapSource.cpp b/src/effects/SkBitmapSource.cpp index 72f51f8423..5e19744a26 100644 --- a/src/effects/SkBitmapSource.cpp +++ b/src/effects/SkBitmapSource.cpp @@ -6,24 +6,71 @@ */ #include "SkBitmapSource.h" +#include "SkDevice.h" +#include "SkCanvas.h" +#include "SkFlattenableBuffers.h" +#include "SkValidationUtils.h" SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap) : INHERITED(0, 0), - fBitmap(bitmap) { + fBitmap(bitmap), + fSrcRect(SkRect::MakeWH(SkIntToScalar(bitmap.width()), + SkIntToScalar(bitmap.height()))), + fDstRect(fSrcRect) { +} + +SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap, const SkRect& srcRect, const SkRect& dstRect) + : INHERITED(0, 0), + fBitmap(bitmap), + fSrcRect(srcRect), + fDstRect(dstRect) { } SkBitmapSource::SkBitmapSource(SkFlattenableReadBuffer& buffer) : INHERITED(0, buffer) { fBitmap.unflatten(buffer); + buffer.readRect(&fSrcRect); + buffer.readRect(&fDstRect); + buffer.validate(SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect)); } void SkBitmapSource::flatten(SkFlattenableWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); fBitmap.flatten(buffer); + buffer.writeRect(fSrcRect); + buffer.writeRect(fDstRect); } -bool SkBitmapSource::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&, +bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix& matrix, SkBitmap* result, SkIPoint* offset) { - *result = fBitmap; + SkRect bounds, dstRect; + fBitmap.getBounds(&bounds); + matrix.mapRect(&dstRect, fDstRect); + if (fSrcRect == bounds && dstRect == bounds) { + *result = fBitmap; + return true; + } + SkIRect dstIRect; + dstRect.roundOut(&dstIRect); + + SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstIRect.width(), dstIRect.height())); + if (NULL == device.get()) { + return false; + } + + SkCanvas canvas(device.get()); + SkPaint paint; + + // Subtract off the integer component of the translation (will be applied in loc, below). + dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop)); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); + // FIXME: this probably shouldn't be necessary, but drawBitmapRectToRect asserts + // None filtering when it's translate-only + paint.setFilterLevel(fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height() ? SkPaint::kNone_FilterLevel : SkPaint::kMedium_FilterLevel); + canvas.drawBitmapRectToRect(fBitmap, &fSrcRect, dstRect, &paint); + + *result = device.get()->accessBitmap(false); + offset->fX += dstIRect.fLeft; + offset->fY += dstIRect.fTop; return true; } |