| Index: gm/filterfastbounds.cpp
|
| diff --git a/gm/filterfastbounds.cpp b/gm/filterfastbounds.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6d4d3f1aa2dbcf579c4a193dbd9623f5ff86f773
|
| --- /dev/null
|
| +++ b/gm/filterfastbounds.cpp
|
| @@ -0,0 +1,336 @@
|
| +/*
|
| + * Copyright 2014 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"
|
| +#include "SkBlurImageFilter.h"
|
| +#include "SkDropShadowImageFilter.h"
|
| +#include "SkMatrixImageFilter.h"
|
| +#include "SkOffsetImageFilter.h"
|
| +#include "SkPictureImageFilter.h"
|
| +#include "SkPictureRecorder.h"
|
| +#include "SkRandom.h"
|
| +
|
| +namespace skiagm {
|
| +
|
| +// Each method of this type must draw its geometry inside 'r' using 'p'
|
| +typedef void(*drawMth)(SkCanvas* canvas, const SkRect& r, const SkPaint& p);
|
| +
|
| +static void draw_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
| + canvas->drawRect(r, p);
|
| +}
|
| +
|
| +static void draw_oval(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
| + canvas->drawOval(r, p);
|
| +}
|
| +
|
| +static void draw_rrect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
| + SkScalar xRad = r.width() / 4.0f;
|
| + SkScalar yRad = r.height() / 4.0f;
|
| +
|
| + SkRRect rr;
|
| + rr.setRectXY(r, xRad, yRad);
|
| + canvas->drawRRect(rr, p);
|
| +}
|
| +
|
| +static void draw_drrect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
| + SkScalar xRad = r.width() / 4.0f;
|
| + SkScalar yRad = r.height() / 4.0f;
|
| +
|
| + SkRRect outer;
|
| + outer.setRectXY(r, xRad, yRad);
|
| + SkRRect inner = outer;
|
| + inner.inset(xRad, yRad);
|
| + canvas->drawDRRect(outer, inner, p);
|
| +}
|
| +
|
| +static void draw_path(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
| + SkPath path;
|
| +
|
| + path.moveTo(r.fLeft, r.fTop);
|
| + path.lineTo(r.fLeft, r.fBottom);
|
| + path.lineTo(r.fRight, r.fBottom);
|
| + path.close();
|
| +
|
| + canvas->drawPath(path, p);
|
| +}
|
| +
|
| +static void draw_points(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
| + SkPoint pts0[2] = { { r.fLeft, r.fTop }, { r.fRight, r.fBottom } };
|
| + SkPoint pts1[2] = { { r.fLeft, r.fBottom }, { r.fRight, r.fTop } };
|
| +
|
| + canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts0, p);
|
| + canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts1, p);
|
| +}
|
| +
|
| +static void draw_bitmap(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
| + SkBitmap bm;
|
| +
|
| + bm.allocN32Pixels(64, 64);
|
| + SkCanvas temp(bm);
|
| + temp.clear(SK_ColorMAGENTA);
|
| +
|
| + canvas->drawBitmapRect(bm, r, &p);
|
| +}
|
| +
|
| +static const drawMth gDrawMthds[] = {
|
| + draw_rect, draw_oval, draw_rrect, draw_drrect, draw_path, draw_points, draw_bitmap
|
| +};
|
| +
|
| +static void add_paint(SkImageFilter* filter, SkTArray<SkPaint>* paints) {
|
| + SkPaint& p = paints->push_back();
|
| + p.setImageFilter(filter);
|
| + SkASSERT(p.canComputeFastBounds());
|
| +}
|
| +
|
| +// Create a selection of imagefilter-based paints to test
|
| +static void create_paints(SkImageFilter* source, SkTArray<SkPaint>* paints) {
|
| + {
|
| + SkMatrix scale;
|
| + scale.setScale(2.0f, 2.0f);
|
| +
|
| + SkAutoTUnref<SkMatrixImageFilter> scaleMIF(
|
| + SkMatrixImageFilter::Create(scale, SkPaint::kLow_FilterLevel, source));
|
| +
|
| + add_paint(scaleMIF, paints);
|
| + }
|
| +
|
| + {
|
| + SkMatrix rot;
|
| + rot.setRotate(-33.3f);
|
| +
|
| + SkAutoTUnref<SkMatrixImageFilter> rotMIF(
|
| + SkMatrixImageFilter::Create(rot, SkPaint::kLow_FilterLevel, source));
|
| +
|
| + add_paint(rotMIF, paints);
|
| + }
|
| +
|
| + {
|
| + static const SkDropShadowImageFilter::ShadowMode kBoth =
|
| + SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode;
|
| +
|
| + SkAutoTUnref<SkDropShadowImageFilter> dsif(
|
| + SkDropShadowImageFilter::Create(10.0f, 10.0f,
|
| + 3.0f, 3.0f,
|
| + SK_ColorRED, kBoth,
|
| + source, NULL, 0));
|
| +
|
| + add_paint(dsif, paints);
|
| + }
|
| +
|
| + {
|
| + SkAutoTUnref<SkDropShadowImageFilter> dsif(
|
| + SkDropShadowImageFilter::Create(27.0f, 27.0f,
|
| + 3.0f, 3.0f,
|
| + SK_ColorRED,
|
| + SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode,
|
| + source, NULL, 0));
|
| +
|
| + add_paint(dsif, paints);
|
| + }
|
| +
|
| + {
|
| + SkAutoTUnref<SkBlurImageFilter> bif(SkBlurImageFilter::Create(3, 3, source));
|
| +
|
| + add_paint(bif, paints);
|
| + }
|
| +
|
| + {
|
| + SkAutoTUnref<SkOffsetImageFilter> oif(SkOffsetImageFilter::Create(15, 15, source));
|
| +
|
| + add_paint(oif, paints);
|
| + }
|
| +}
|
| +
|
| +// This GM visualizes the fast bounds for various combinations of geometry
|
| +// and image filter
|
| +class ImageFilterFastBoundGM : public GM {
|
| +public:
|
| + ImageFilterFastBoundGM() {
|
| + this->setBGColor(0xFFCCCCCC);
|
| + }
|
| +
|
| +protected:
|
| + static const int kTileWidth = 100;
|
| + static const int kTileHeight = 100;
|
| + static const int kNumVertTiles = 6;
|
| + static const int kNumXtraCols = 2;
|
| +
|
| + // SkPictureImageFilter doesn't support serialization yet.
|
| + uint32_t onGetFlags() const SK_OVERRIDE {
|
| + return kSkipPicture_Flag |
|
| + kSkipPipe_Flag |
|
| + kSkipPipeCrossProcess_Flag |
|
| + kSkipTiled_Flag |
|
| + kSkipScaledReplay_Flag;
|
| + }
|
| +
|
| + SkString onShortName() SK_OVERRIDE{ return SkString("filterfastbounds"); }
|
| +
|
| + SkISize onISize() SK_OVERRIDE{
|
| + return SkISize::Make((SK_ARRAY_COUNT(gDrawMthds) + kNumXtraCols) * kTileWidth,
|
| + kNumVertTiles * kTileHeight);
|
| + }
|
| +
|
| + static void draw_geom_with_paint(drawMth draw, const SkIPoint& off,
|
| + SkCanvas* canvas, const SkPaint& p) {
|
| + SkPaint redStroked;
|
| + redStroked.setColor(SK_ColorRED);
|
| + redStroked.setStyle(SkPaint::kStroke_Style);
|
| +
|
| + SkPaint blueStroked;
|
| + blueStroked.setColor(SK_ColorBLUE);
|
| + blueStroked.setStyle(SkPaint::kStroke_Style);
|
| +
|
| + const SkRect r = SkRect::MakeLTRB(20, 20, 30, 30);
|
| + SkRect storage;
|
| +
|
| + canvas->save();
|
| + canvas->translate(SkIntToScalar(off.fX), SkIntToScalar(off.fY));
|
| + canvas->scale(1.5f, 1.5f);
|
| +
|
| + const SkRect& fastBound = p.computeFastBounds(r, &storage);
|
| +
|
| + canvas->save();
|
| + canvas->clipRect(fastBound);
|
| + (*draw)(canvas, r, p);
|
| + canvas->restore();
|
| +
|
| + canvas->drawRect(r, redStroked);
|
| + canvas->drawRect(fastBound, blueStroked);
|
| + canvas->restore();
|
| + }
|
| +
|
| + static void draw_savelayer_with_paint(const SkIPoint& off,
|
| + SkCanvas* canvas,
|
| + const SkPaint& p) {
|
| + SkPaint redStroked;
|
| + redStroked.setColor(SK_ColorRED);
|
| + redStroked.setStyle(SkPaint::kStroke_Style);
|
| +
|
| + SkPaint blueStroked;
|
| + blueStroked.setColor(SK_ColorBLUE);
|
| + blueStroked.setStyle(SkPaint::kStroke_Style);
|
| +
|
| + const SkRect bounds = SkRect::MakeWH(10, 10);
|
| + SkRect storage;
|
| +
|
| + canvas->save();
|
| + canvas->translate(30, 30);
|
| + canvas->translate(SkIntToScalar(off.fX), SkIntToScalar(off.fY));
|
| + canvas->scale(1.5f, 1.5f);
|
| +
|
| + const SkRect& fastBound = p.computeFastBounds(bounds, &storage);
|
| +
|
| + canvas->saveLayer(&fastBound, &p);
|
| + canvas->restore();
|
| +
|
| + canvas->drawRect(bounds, redStroked);
|
| + canvas->drawRect(fastBound, blueStroked);
|
| + canvas->restore();
|
| + }
|
| +
|
| + void onDraw(SkCanvas* canvas) SK_OVERRIDE{
|
| +
|
| + SkPaint blackFill;
|
| +
|
| + //-----------
|
| + // Normal paints (no source)
|
| + SkTArray<SkPaint> paints;
|
| + create_paints(NULL, &paints);
|
| +
|
| + //-----------
|
| + // Paints with a PictureImageFilter as a source
|
| + SkAutoTUnref<SkPicture> pic;
|
| +
|
| + {
|
| + SkPictureRecorder rec;
|
| +
|
| + SkCanvas* c = rec.beginRecording(10, 10);
|
| + c->drawRect(SkRect::MakeWH(10, 10), blackFill);
|
| + pic.reset(rec.endRecording());
|
| + }
|
| +
|
| + SkAutoTUnref<SkPictureImageFilter> pif(SkPictureImageFilter::Create(pic));
|
| +
|
| + SkTArray<SkPaint> pifPaints;
|
| + create_paints(pif, &pifPaints);
|
| +
|
| + //-----------
|
| + // Paints with a BitmapSource as a source
|
| + SkBitmap bm;
|
| +
|
| + {
|
| + SkPaint p;
|
| + bm.allocN32Pixels(10, 10);
|
| + SkCanvas temp(bm);
|
| + temp.clear(SK_ColorYELLOW);
|
| + p.setColor(SK_ColorBLUE);
|
| + temp.drawRect(SkRect::MakeLTRB(5, 5, 10, 10), p);
|
| + p.setColor(SK_ColorGREEN);
|
| + temp.drawRect(SkRect::MakeLTRB(5, 0, 10, 5), p);
|
| + }
|
| +
|
| + SkAutoTUnref<SkBitmapSource> bms(SkBitmapSource::Create(bm));
|
| +
|
| + SkTArray<SkPaint> bmsPaints;
|
| + create_paints(bms, &bmsPaints);
|
| +
|
| + //-----------
|
| + SkASSERT(paints.count() == kNumVertTiles);
|
| + SkASSERT(paints.count() == pifPaints.count());
|
| + SkASSERT(paints.count() == bmsPaints.count());
|
| +
|
| + // horizontal separators
|
| + for (int i = 1; i < paints.count(); ++i) {
|
| + canvas->drawLine(0,
|
| + i*SkIntToScalar(kTileHeight),
|
| + SkIntToScalar((SK_ARRAY_COUNT(gDrawMthds) + kNumXtraCols)*kTileWidth),
|
| + i*SkIntToScalar(kTileHeight),
|
| + blackFill);
|
| + }
|
| + // vertical separators
|
| + for (int i = 0; i < (int)SK_ARRAY_COUNT(gDrawMthds) + kNumXtraCols; ++i) {
|
| + canvas->drawLine(SkIntToScalar(i * kTileWidth),
|
| + 0,
|
| + SkIntToScalar(i * kTileWidth),
|
| + SkIntToScalar(paints.count() * kTileWidth),
|
| + blackFill);
|
| + }
|
| +
|
| + // A column of saveLayers with PictureImageFilters
|
| + for (int i = 0; i < pifPaints.count(); ++i) {
|
| + draw_savelayer_with_paint(SkIPoint::Make(0, i*kTileHeight),
|
| + canvas, pifPaints[i]);
|
| + }
|
| +
|
| + // A column of saveLayers with BitmapSources
|
| + for (int i = 0; i < pifPaints.count(); ++i) {
|
| + draw_savelayer_with_paint(SkIPoint::Make(kTileWidth, i*kTileHeight),
|
| + canvas, bmsPaints[i]);
|
| + }
|
| +
|
| + // Multiple columns with different geometry
|
| + for (int i = 0; i < (int)SK_ARRAY_COUNT(gDrawMthds); ++i) {
|
| + for (int j = 0; j < paints.count(); ++j) {
|
| + draw_geom_with_paint(*gDrawMthds[i],
|
| + SkIPoint::Make((i+kNumXtraCols) * kTileWidth, j*kTileHeight),
|
| + canvas, paints[j]);
|
| + }
|
| + }
|
| +
|
| + }
|
| +
|
| +private:
|
| + typedef GM INHERITED;
|
| +};
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +DEF_GM(return SkNEW(ImageFilterFastBoundGM);)
|
| +
|
| +}
|
|
|