141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com/*
241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com * Copyright 2013 Google Inc.
341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com *
441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com * found in the LICENSE file.
641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com */
741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com#include "gm.h"
9b7061176c7f414616fe2e79e832b3e0abe326af6robertphillips@google.com#include "SkBlurMask.h"
1041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com#include "SkBlurMaskFilter.h"
11b7061176c7f414616fe2e79e832b3e0abe326af6robertphillips@google.com#include "SkCanvas.h"
1241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com#include "SkColorFilter.h"
13b7061176c7f414616fe2e79e832b3e0abe326af6robertphillips@google.com#include "SkLayerDrawLooper.h"
1441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
1541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com// This GM tests 3 different ways of drawing four shadows around a square:
1641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com//      just using 4 blurred rects
1741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com//      using 4 1-level draw loopers
1841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com//      using 1 4-level draw looper
1941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com// They all produce exactly the same pixels
2041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.comclass MegaLooperGM : public skiagm::GM {
2141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.compublic:
2241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // The types define "<# of loopers> x <# of stages per looper>"
2341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    enum Type {
2441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        k0x0_Type,  // draw without loopers at all
2541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        k4x1_Type,  // a looper for each shadow
2641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        k1x4_Type,  // all four shadows in one looper
2741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    };
2841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
2941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    MegaLooperGM(Type type) : fType(type) {}
3041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
3141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.comprotected:
3241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    virtual SkString onShortName() {
3341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        switch (fType) {
3441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        case k0x0_Type:
3541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            return SkString("megalooper_0x0");
3641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            break;
3741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        case k4x1_Type:
3841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            return SkString("megalooper_4x1");
3941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            break;
4041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        case k1x4_Type:     // fall through
4141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        default:
4241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            return SkString("megalooper_1x4");
4341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            break;
4441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        }
4541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
4641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
4741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    virtual SkISize onISize() {
4841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        return SkISize::Make(kWidth, kHeight);
4941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
5041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
5141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    virtual void onDraw(SkCanvas* canvas) {
5241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        for (int y = 100; y < kHeight; y += 200) {
5341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            for (int x = 100; x < kWidth; x += 200) {
5441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                switch (fType) {
5541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                    case k0x0_Type:
5641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                        draw0x0(canvas, SkIntToScalar(x), SkIntToScalar(y));
5741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                        break;
5841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                    case k4x1_Type:
5941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                        draw4x1(canvas, SkIntToScalar(x), SkIntToScalar(y));
6041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                        break;
6141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                    case k1x4_Type:     // fall through
6241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                    default:
6341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                        draw1x4(canvas, SkIntToScalar(x), SkIntToScalar(y));
6441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                        break;
6541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                }
6641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            }
6741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        }
6841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
6941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
7041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.comprivate:
7141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    static const int kWidth = 800;
7241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    static const int kHeight = 800;
7341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    static const int kHalfOuterClipSize = 100;
7441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    static const int kHalfSquareSize = 50;
7541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    static const int kOffsetToOutsideClip = kHalfSquareSize + kHalfOuterClipSize + 1;
7641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
7741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    static const SkPoint gBlurOffsets[4];
7841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    static const SkColor gColors[4];
7941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    Type fType;
8041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
8141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // Just draw a blurred rect at each of the four corners of a square (centered at x,y).
8241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // Use two clips to define a rectori where we want pixels to appear.
8341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    void draw0x0(SkCanvas* canvas, SkScalar x, SkScalar y) {
8441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        SkRect innerClip = { -kHalfSquareSize, -kHalfSquareSize, kHalfSquareSize, kHalfSquareSize };
8541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        innerClip.offset(x, y);
8641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
8711f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com        SkRect outerClip = {
8811f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com            -kHalfOuterClipSize-kHalfSquareSize, -kHalfOuterClipSize-kHalfSquareSize,
8941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com             kHalfOuterClipSize+kHalfSquareSize,  kHalfOuterClipSize+kHalfSquareSize
9041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        };
9141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        outerClip.offset(x, y);
9241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
9341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        canvas->save();
9441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        canvas->clipRect(outerClip, SkRegion::kIntersect_Op);
9541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        canvas->clipRect(innerClip, SkRegion::kDifference_Op);
9641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
9741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        SkPaint paint;
9841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        paint.setAntiAlias(true);
9941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        paint.setMaskFilter(createBlur())->unref();
10041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
10141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        for (int i = 0; i < 4; ++i) {
10241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            paint.setColor(gColors[i]);
10341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
10441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            SkRect rect = { -kHalfSquareSize, -kHalfSquareSize, kHalfSquareSize, kHalfSquareSize };
10541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            rect.offset(gBlurOffsets[i]);
10641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            rect.offset(x, y);
10741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            canvas->drawRect(rect, paint);
10841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        }
10941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
11041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        canvas->restore();
11141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
11241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
11341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    SkMaskFilter* createBlur() {
114b7061176c7f414616fe2e79e832b3e0abe326af6robertphillips@google.com        static const SkScalar kBlurSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(25));
11541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
116e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org        return SkBlurMaskFilter::Create(kNormal_SkBlurStyle, kBlurSigma,
11741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                                        SkBlurMaskFilter::kHighQuality_BlurFlag);
11841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
11941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
12041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // This draws 4 blurred shadows around a single square (centered at x, y).
12141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // Each blur is offset +/- half the square's side in x & y from the original
12241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // (so each blurred rect is centered at one of the corners of the original).
12341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // For each blur a large outer clip is centered around the blurred rect
12441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // while a difference clip stays at the location of the original rect.
12541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // Each blurred rect is drawn with a draw looper where the original (non-
12641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // blurred rect) is offset to reside outside of the large outer clip (so
12711f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com    // it never appears) but the offset in the draw looper is used to translate
12841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // the blurred version back into the clip.
12941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    void draw4x1(SkCanvas* canvas, SkScalar x, SkScalar y) {
13041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
13141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        for (int i = 0; i < 4; ++i) {
13241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            SkPaint loopPaint;
13341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
134ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org            loopPaint.setLooper(create1Looper(-kOffsetToOutsideClip, 0, gColors[i]))->unref();
13541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            loopPaint.setAntiAlias(true);
13641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
13711f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com            SkRect outerClip = {
13811f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com                -kHalfOuterClipSize, -kHalfOuterClipSize,
13911f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com                kHalfOuterClipSize, kHalfOuterClipSize
14041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            };
14141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            outerClip.offset(x, y);
14241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            // center it on the blurred rect
14341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            outerClip.offset(gBlurOffsets[i]);
14441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
14541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            SkRect rect = { -kHalfSquareSize, -kHalfSquareSize, kHalfSquareSize, kHalfSquareSize };
14641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            rect.offset(x, y);
14741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
14841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            canvas->save();
14941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                canvas->clipRect(outerClip, SkRegion::kIntersect_Op);
15041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                canvas->clipRect(rect, SkRegion::kDifference_Op);
15141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
15241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                // move the rect to where we want the blur to appear
15341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                rect.offset(gBlurOffsets[i]);
15441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                // then move it outside the clip (the blur stage of the draw
15541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                // looper will undo this translation)
15641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                rect.offset(SkIntToScalar(kOffsetToOutsideClip), 0);
15741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
15841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                canvas->drawRect(rect, loopPaint);
15941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            canvas->restore();
16041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        }
16141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
16241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
16311f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com    // Create a 1-tier drawlooper
16441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    SkLayerDrawLooper* create1Looper(SkScalar xOff, SkScalar yOff, SkColor color) {
16573cb15351f33459e0c861a96135c634dec77ef9dcommit-bot@chromium.org        SkLayerDrawLooper::Builder looperBuilder;
16641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        SkLayerDrawLooper::LayerInfo info;
16741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
16841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        info.fPaintBits = SkLayerDrawLooper::kColorFilter_Bit |
16941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                          SkLayerDrawLooper::kMaskFilter_Bit;
17041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        info.fColorMode = SkXfermode::kSrc_Mode;
17141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        info.fOffset.set(xOff, yOff);
17241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        info.fPostTranslate = false;
17341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
17473cb15351f33459e0c861a96135c634dec77ef9dcommit-bot@chromium.org        SkPaint* paint = looperBuilder.addLayer(info);
17541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
17641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        paint->setMaskFilter(this->createBlur())->unref();
17741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
17841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        SkColorFilter* cf = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);
17941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        paint->setColorFilter(cf)->unref();
18041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
18173cb15351f33459e0c861a96135c634dec77ef9dcommit-bot@chromium.org        return looperBuilder.detachLooper();
18241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
18341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
18441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    void draw1x4(SkCanvas* canvas, SkScalar x, SkScalar y) {
18541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        SkRect rect = { -kHalfSquareSize, -kHalfSquareSize, kHalfSquareSize, kHalfSquareSize };
18641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        rect.offset(x, y);
18741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
18811f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com        SkRect outerClip = {
18911f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com            -kHalfOuterClipSize-kHalfSquareSize, -kHalfOuterClipSize-kHalfSquareSize,
19041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com             kHalfOuterClipSize+kHalfSquareSize,  kHalfOuterClipSize+kHalfSquareSize
19141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        };
19241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        outerClip.offset(x, y);
19341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
19441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        SkPaint paint;
19541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        paint.setAntiAlias(true);
196ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org        paint.setLooper(create4Looper(-kOffsetToOutsideClip-kHalfSquareSize, 0))->unref();
19741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
19841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        canvas->save();
19941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            canvas->clipRect(outerClip, SkRegion::kIntersect_Op);
20041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            canvas->clipRect(rect, SkRegion::kDifference_Op);
20141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
20241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            rect.offset(SkIntToScalar(kOffsetToOutsideClip+kHalfSquareSize), 0);
20341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            canvas->drawRect(rect, paint);
20441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        canvas->restore();
20541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
20641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
20741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    // Create a 4-tier draw looper
20841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    SkLayerDrawLooper* create4Looper(SkScalar xOff, SkScalar yOff) {
20973cb15351f33459e0c861a96135c634dec77ef9dcommit-bot@chromium.org        SkLayerDrawLooper::Builder looperBuilder;
21041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        SkLayerDrawLooper::LayerInfo info;
21141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
21241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        info.fPaintBits = SkLayerDrawLooper::kColorFilter_Bit |
21341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com                          SkLayerDrawLooper::kMaskFilter_Bit;
21441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        info.fColorMode = SkXfermode::kSrc_Mode;
21541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        info.fPostTranslate = false;
21641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
21741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        SkPaint* paint;
21841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
21941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        for (int i = 3; i >= 0; --i) {
22041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            info.fOffset.set(xOff+gBlurOffsets[i].fX, yOff+gBlurOffsets[i].fY);
22173cb15351f33459e0c861a96135c634dec77ef9dcommit-bot@chromium.org            paint = looperBuilder.addLayer(info);
22241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
22341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            paint->setMaskFilter(this->createBlur())->unref();
22441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
22541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            SkColorFilter* cf = SkColorFilter::CreateModeFilter(gColors[i], SkXfermode::kSrcIn_Mode);
22641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com            paint->setColorFilter(cf)->unref();
22741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com        }
22841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
22973cb15351f33459e0c861a96135c634dec77ef9dcommit-bot@chromium.org        return looperBuilder.detachLooper();
23041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    }
23141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
23241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    typedef GM INHERITED;
23341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com};
23441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
23541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.comconst SkPoint MegaLooperGM::gBlurOffsets[4] = {
23611f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com    {  kHalfSquareSize,  kHalfSquareSize },
23711f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com    { -kHalfSquareSize,  kHalfSquareSize },
23811f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com    {  kHalfSquareSize, -kHalfSquareSize },
23941570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    { -kHalfSquareSize, -kHalfSquareSize }
24041570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com};
24141570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
24241570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.comconst SkColor MegaLooperGM::gColors[4] = {
24341570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com    SK_ColorGREEN, SK_ColorYELLOW, SK_ColorBLUE, SK_ColorRED
24441570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com};
24541570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.com
24641570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.comDEF_GM( return new MegaLooperGM(MegaLooperGM::k0x0_Type); )
24741570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.comDEF_GM( return new MegaLooperGM(MegaLooperGM::k4x1_Type); )
24841570854703ae432c1c9bf335399727ff3eadb21robertphillips@google.comDEF_GM( return new MegaLooperGM(MegaLooperGM::k1x4_Type); )
249