12ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt/*
22ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt * Copyright 2015 Google Inc.
32ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt *
42ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt * Use of this source code is governed by a BSD-style license that can be
52ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt * found in the LICENSE file.
62ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt */
72ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
82ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt#include "gm.h"
92ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt#include "SkColorPriv.h"
102ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt#include "SkGradientShader.h"
112ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt#include "SkImage.h"
124dbbd04314cc0606f8d3bafe515c97e52c180f73halcanary#include "SkMathPriv.h"
132ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt#include "SkRandom.h"
142ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt#include "SkShader.h"
152ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt#include "SkSurface.h"
162ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
17876c841f9b4c57c404c572de1c862e39cc6a05a4Brian Osmanstatic sk_sp<SkImage> makebm(int w, int h) {
182ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
19876c841f9b4c57c404c572de1c862e39cc6a05a4Brian Osman    auto surface(SkSurface::MakeRaster(info));
202ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkCanvas* canvas = surface->getCanvas();
212ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
222ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    const SkScalar wScalar = SkIntToScalar(w);
232ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    const SkScalar hScalar = SkIntToScalar(h);
242ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
252ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    const SkPoint     pt = { wScalar / 2, hScalar / 2 };
262ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
272ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    const SkScalar    radius = 4 * SkMaxScalar(wScalar, hScalar);
282ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
29dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    constexpr SkColor     colors[] = { SK_ColorRED, SK_ColorYELLOW,
302ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                          SK_ColorGREEN, SK_ColorMAGENTA,
312ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                          SK_ColorBLUE, SK_ColorCYAN,
322ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                          SK_ColorRED};
332ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
34dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    constexpr SkScalar    pos[] = {0,
352ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      SK_Scalar1 / 6,
362ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      2 * SK_Scalar1 / 6,
372ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      3 * SK_Scalar1 / 6,
382ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      4 * SK_Scalar1 / 6,
392ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      5 * SK_Scalar1 / 6,
402ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      SK_Scalar1};
412ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
422ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkASSERT(SK_ARRAY_COUNT(colors) == SK_ARRAY_COUNT(pos));
432ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkPaint     paint;
442ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkRect rect = SkRect::MakeWH(wScalar, hScalar);
452ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkMatrix mat = SkMatrix::I();
462ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    for (int i = 0; i < 4; ++i) {
472ad1aa67c6894696cdd65ec56057f81031d1c24areed        paint.setShader(SkGradientShader::MakeRadial(
482ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        pt, radius,
492ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        colors, pos,
502ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        SK_ARRAY_COUNT(colors),
512ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        SkShader::kRepeat_TileMode,
522ad1aa67c6894696cdd65ec56057f81031d1c24areed                        0, &mat));
532ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        canvas->drawRect(rect, paint);
542ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        rect.inset(wScalar / 8, hScalar / 8);
552ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        mat.postScale(SK_Scalar1 / 4, SK_Scalar1 / 4);
562ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    }
579ce9d6772df650ceb0511f275e1a83dffa78ff72reed    return surface->makeImageSnapshot();
582ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt}
592ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
60dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr int gSize = 1024;
61dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr int gSurfaceSize = 2048;
622ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
6309d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon// This GM calls drawImageRect several times using the same texture. This is intended to exercise
6409d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon// combining GrDrawOps during these calls.
652ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittclass DrawMiniBitmapRectGM : public skiagm::GM {
662ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittpublic:
672ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    DrawMiniBitmapRectGM(bool antiAlias) : fAA(antiAlias) {
682ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        fName.set("drawminibitmaprect");
692ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        if (fAA) {
702ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt            fName.appendf("_aa");
712ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        }
722ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    }
732ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
742ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittprotected:
752ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkString onShortName() override { return fName; }
762ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
772ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkISize onISize() override { return SkISize::Make(gSize, gSize); }
782ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
792ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    void onDraw(SkCanvas* canvas) override {
8096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fImage) {
81876c841f9b4c57c404c572de1c862e39cc6a05a4Brian Osman            fImage = makebm(gSurfaceSize, gSurfaceSize);
822ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        }
832ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
842ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        const SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)};
85dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const int kMaxSrcRectSize = 1 << (SkNextLog2(gSurfaceSize) + 2);
862ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
87dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr int kPadX = 30;
88dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr int kPadY = 40;
892ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
902ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        int rowCount = 0;
912ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY));
922ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        canvas->save();
932ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        SkRandom random;
942ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
952ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        SkPaint paint;
962ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        paint.setAntiAlias(fAA);
972ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        for (int w = 1; w <= kMaxSrcRectSize; w *= 3) {
982ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt            for (int h = 1; h <= kMaxSrcRectSize; h *= 3) {
992ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1002ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                const SkIRect srcRect =
1012ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        SkIRect::MakeXYWH((gSurfaceSize - w) / 2, (gSurfaceSize - h) / 2, w, h);
1022ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                canvas->save();
1032ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                switch (random.nextU() % 3) {
1042ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    case 0:
1052ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        canvas->rotate(random.nextF() * 10.f);
1062ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        break;
1072ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    case 1:
1082ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        canvas->rotate(-random.nextF() * 10.f);
1092ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        break;
1102ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    case 2:
1112ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        // rect stays rect
1122ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        break;
1132ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                }
1149ce9d6772df650ceb0511f275e1a83dffa78ff72reed                canvas->drawImageRect(fImage.get(), srcRect, dstRect, &paint,
1152ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      SkCanvas::kFast_SrcRectConstraint);
1162ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                canvas->restore();
1172ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1182ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0);
1192ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                ++rowCount;
1202ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                if ((dstRect.width() + 2 * kPadX) * rowCount > gSize) {
1212ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    canvas->restore();
1222ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY);
1232ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    canvas->save();
1242ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    rowCount = 0;
1252ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                }
1262ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt            }
1272ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        }
1282ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        canvas->restore();
1292ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    }
1302ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1312ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittprivate:
1329ce9d6772df650ceb0511f275e1a83dffa78ff72reed    bool            fAA;
1339ce9d6772df650ceb0511f275e1a83dffa78ff72reed    sk_sp<SkImage>  fImage;
1349ce9d6772df650ceb0511f275e1a83dffa78ff72reed    SkString        fName;
1352ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1362ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    typedef skiagm::GM INHERITED;
1372ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt};
1382ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1392ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittDEF_GM( return new DrawMiniBitmapRectGM(true); )
1402ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittDEF_GM( return new DrawMiniBitmapRectGM(false); )
141