17e4186accea094276c9f3c65c64e63ffc59aa644reed/*
27e4186accea094276c9f3c65c64e63ffc59aa644reed * Copyright 2015 Google Inc.
37e4186accea094276c9f3c65c64e63ffc59aa644reed *
47e4186accea094276c9f3c65c64e63ffc59aa644reed * Use of this source code is governed by a BSD-style license that can be
57e4186accea094276c9f3c65c64e63ffc59aa644reed * found in the LICENSE file.
67e4186accea094276c9f3c65c64e63ffc59aa644reed */
77e4186accea094276c9f3c65c64e63ffc59aa644reed
87e4186accea094276c9f3c65c64e63ffc59aa644reed#include "gm.h"
97e4186accea094276c9f3c65c64e63ffc59aa644reed#include "SkImageFilter.h"
107e4186accea094276c9f3c65c64e63ffc59aa644reed#include "SkColorMatrixFilter.h"
117e4186accea094276c9f3c65c64e63ffc59aa644reed
127e4186accea094276c9f3c65c64e63ffc59aa644reed/**
137e4186accea094276c9f3c65c64e63ffc59aa644reed *  Test drawing a primitive w/ an imagefilter (in this case, just matrix w/ identity) to see
147e4186accea094276c9f3c65c64e63ffc59aa644reed *  that we apply the xfermode *after* the image has been created and filtered, and not during
157e4186accea094276c9f3c65c64e63ffc59aa644reed *  the creation step (i.e. before it is filtered).
167e4186accea094276c9f3c65c64e63ffc59aa644reed *
177e4186accea094276c9f3c65c64e63ffc59aa644reed *  see skbug.com/3741
187e4186accea094276c9f3c65c64e63ffc59aa644reed */
197e4186accea094276c9f3c65c64e63ffc59aa644reedclass ImageFilterXfermodeTestGM : public skiagm::GM {
207e4186accea094276c9f3c65c64e63ffc59aa644reedprotected:
217e4186accea094276c9f3c65c64e63ffc59aa644reed    SkString onShortName() override {
227e4186accea094276c9f3c65c64e63ffc59aa644reed        return SkString("imagefilters_xfermodes");
237e4186accea094276c9f3c65c64e63ffc59aa644reed    }
247e4186accea094276c9f3c65c64e63ffc59aa644reed
257e4186accea094276c9f3c65c64e63ffc59aa644reed    SkISize onISize() override { return SkISize::Make(480, 480); }
267e4186accea094276c9f3c65c64e63ffc59aa644reed
277e4186accea094276c9f3c65c64e63ffc59aa644reed    void doDraw(SkCanvas* canvas, SkXfermode::Mode mode, SkImageFilter* imf) {
2849124378913f3467eb67e653b3b48f80899a3f37reed        SkAutoCanvasRestore acr(canvas, true);
2949124378913f3467eb67e653b3b48f80899a3f37reed        canvas->clipRect(SkRect::MakeWH(220, 220));
3049124378913f3467eb67e653b3b48f80899a3f37reed
3149124378913f3467eb67e653b3b48f80899a3f37reed        // want to force a layer, so modes like DstIn can combine meaningfully, but the final
3249124378913f3467eb67e653b3b48f80899a3f37reed        // image can still be shown against our default (opaque) background. non-opaque GMs
3349124378913f3467eb67e653b3b48f80899a3f37reed        // are a lot more trouble to compare/triage.
3449124378913f3467eb67e653b3b48f80899a3f37reed        canvas->saveLayer(NULL, NULL);
3549124378913f3467eb67e653b3b48f80899a3f37reed        canvas->drawColor(SK_ColorGREEN);
3649124378913f3467eb67e653b3b48f80899a3f37reed
377e4186accea094276c9f3c65c64e63ffc59aa644reed        SkPaint paint;
387e4186accea094276c9f3c65c64e63ffc59aa644reed        paint.setAntiAlias(true);
397e4186accea094276c9f3c65c64e63ffc59aa644reed
407e4186accea094276c9f3c65c64e63ffc59aa644reed        SkRect r0 = SkRect::MakeXYWH(10, 60, 200, 100);
417e4186accea094276c9f3c65c64e63ffc59aa644reed        SkRect r1 = SkRect::MakeXYWH(60, 10, 100, 200);
427e4186accea094276c9f3c65c64e63ffc59aa644reed
437e4186accea094276c9f3c65c64e63ffc59aa644reed        paint.setColor(SK_ColorRED);
447e4186accea094276c9f3c65c64e63ffc59aa644reed        canvas->drawOval(r0, paint);
457e4186accea094276c9f3c65c64e63ffc59aa644reed
4649124378913f3467eb67e653b3b48f80899a3f37reed        paint.setColor(0x660000FF);
477e4186accea094276c9f3c65c64e63ffc59aa644reed        paint.setImageFilter(imf);
487e4186accea094276c9f3c65c64e63ffc59aa644reed        paint.setXfermodeMode(mode);
497e4186accea094276c9f3c65c64e63ffc59aa644reed        canvas->drawOval(r1, paint);
507e4186accea094276c9f3c65c64e63ffc59aa644reed    }
517e4186accea094276c9f3c65c64e63ffc59aa644reed
527e4186accea094276c9f3c65c64e63ffc59aa644reed    void onDraw(SkCanvas* canvas) override {
5349124378913f3467eb67e653b3b48f80899a3f37reed        canvas->translate(10, 10);
5449124378913f3467eb67e653b3b48f80899a3f37reed
557e4186accea094276c9f3c65c64e63ffc59aa644reed        // just need an imagefilter to trigger the code-path (which creates a tmp layer)
567e4186accea094276c9f3c65c64e63ffc59aa644reed        SkAutoTUnref<SkImageFilter> imf(SkImageFilter::CreateMatrixFilter(SkMatrix::I(),
577e4186accea094276c9f3c65c64e63ffc59aa644reed                                                                          kNone_SkFilterQuality));
587e4186accea094276c9f3c65c64e63ffc59aa644reed
597e4186accea094276c9f3c65c64e63ffc59aa644reed        const SkXfermode::Mode modes[] = {
607e4186accea094276c9f3c65c64e63ffc59aa644reed            SkXfermode::kSrcATop_Mode, SkXfermode::kDstIn_Mode
617e4186accea094276c9f3c65c64e63ffc59aa644reed        };
627e4186accea094276c9f3c65c64e63ffc59aa644reed
637e4186accea094276c9f3c65c64e63ffc59aa644reed        for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
647e4186accea094276c9f3c65c64e63ffc59aa644reed            canvas->save();
657e4186accea094276c9f3c65c64e63ffc59aa644reed            this->doDraw(canvas, modes[i], NULL);
6649124378913f3467eb67e653b3b48f80899a3f37reed            canvas->translate(240, 0);
677e4186accea094276c9f3c65c64e63ffc59aa644reed            this->doDraw(canvas, modes[i], imf);
687e4186accea094276c9f3c65c64e63ffc59aa644reed            canvas->restore();
697e4186accea094276c9f3c65c64e63ffc59aa644reed
7049124378913f3467eb67e653b3b48f80899a3f37reed            canvas->translate(0, 240);
717e4186accea094276c9f3c65c64e63ffc59aa644reed        }
727e4186accea094276c9f3c65c64e63ffc59aa644reed    }
737e4186accea094276c9f3c65c64e63ffc59aa644reed
747e4186accea094276c9f3c65c64e63ffc59aa644reedprivate:
757e4186accea094276c9f3c65c64e63ffc59aa644reed    typedef GM INHERITED;
767e4186accea094276c9f3c65c64e63ffc59aa644reed};
777e4186accea094276c9f3c65c64e63ffc59aa644reedDEF_GM( return new ImageFilterXfermodeTestGM; )
787e4186accea094276c9f3c65c64e63ffc59aa644reed
79