aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/bitmapsource.cpp95
-rw-r--r--gm/tileimagefilter.cpp5
-rw-r--r--gm/xfermodeimagefilter.cpp44
-rw-r--r--gyp/gmslides.gypi1
-rw-r--r--include/effects/SkBitmapSource.h2
-rw-r--r--src/effects/SkBitmapSource.cpp53
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;
}