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
179ce9d6772df650ceb0511f275e1a83dffa78ff72reedstatic sk_sp<SkImage> makebm(SkCanvas* caller, int w, int h) {
182ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
19e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    auto surface(caller->makeSurface(info));
2096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == surface) {
21e8f3062a36d3682f4019309a32b5b84dc9eddf8creed        surface = SkSurface::MakeRaster(info);
222ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    }
232ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkCanvas* canvas = surface->getCanvas();
242ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
252ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    const SkScalar wScalar = SkIntToScalar(w);
262ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    const SkScalar hScalar = SkIntToScalar(h);
272ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
282ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    const SkPoint     pt = { wScalar / 2, hScalar / 2 };
292ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
302ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    const SkScalar    radius = 4 * SkMaxScalar(wScalar, hScalar);
312ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
32dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    constexpr SkColor     colors[] = { SK_ColorRED, SK_ColorYELLOW,
332ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                          SK_ColorGREEN, SK_ColorMAGENTA,
342ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                          SK_ColorBLUE, SK_ColorCYAN,
352ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                          SK_ColorRED};
362ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
37dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    constexpr SkScalar    pos[] = {0,
382ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      SK_Scalar1 / 6,
392ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      2 * SK_Scalar1 / 6,
402ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      3 * SK_Scalar1 / 6,
412ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      4 * SK_Scalar1 / 6,
422ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      5 * SK_Scalar1 / 6,
432ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      SK_Scalar1};
442ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
452ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkASSERT(SK_ARRAY_COUNT(colors) == SK_ARRAY_COUNT(pos));
462ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkPaint     paint;
472ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkRect rect = SkRect::MakeWH(wScalar, hScalar);
482ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkMatrix mat = SkMatrix::I();
492ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    for (int i = 0; i < 4; ++i) {
502ad1aa67c6894696cdd65ec56057f81031d1c24areed        paint.setShader(SkGradientShader::MakeRadial(
512ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        pt, radius,
522ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        colors, pos,
532ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        SK_ARRAY_COUNT(colors),
542ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        SkShader::kRepeat_TileMode,
552ad1aa67c6894696cdd65ec56057f81031d1c24areed                        0, &mat));
562ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        canvas->drawRect(rect, paint);
572ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        rect.inset(wScalar / 8, hScalar / 8);
582ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        mat.postScale(SK_Scalar1 / 4, SK_Scalar1 / 4);
592ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    }
609ce9d6772df650ceb0511f275e1a83dffa78ff72reed    return surface->makeImageSnapshot();
612ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt}
622ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
63dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr int gSize = 1024;
64dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr int gSurfaceSize = 2048;
652ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
6609d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon// This GM calls drawImageRect several times using the same texture. This is intended to exercise
6709d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon// combining GrDrawOps during these calls.
682ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittclass DrawMiniBitmapRectGM : public skiagm::GM {
692ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittpublic:
702ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    DrawMiniBitmapRectGM(bool antiAlias) : fAA(antiAlias) {
712ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        fName.set("drawminibitmaprect");
722ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        if (fAA) {
732ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt            fName.appendf("_aa");
742ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        }
752ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    }
762ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
772ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittprotected:
782ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkString onShortName() override { return fName; }
792ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
802ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    SkISize onISize() override { return SkISize::Make(gSize, gSize); }
812ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
822ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    void onDraw(SkCanvas* canvas) override {
8396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fImage) {
849ce9d6772df650ceb0511f275e1a83dffa78ff72reed            fImage = makebm(canvas, gSurfaceSize, gSurfaceSize);
852ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        }
862ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
872ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        const SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)};
88dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const int kMaxSrcRectSize = 1 << (SkNextLog2(gSurfaceSize) + 2);
892ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
90dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr int kPadX = 30;
91dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr int kPadY = 40;
922ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
932ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        int rowCount = 0;
942ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY));
952ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        canvas->save();
962ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        SkRandom random;
972ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
982ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        SkPaint paint;
992ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        paint.setAntiAlias(fAA);
1002ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        for (int w = 1; w <= kMaxSrcRectSize; w *= 3) {
1012ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt            for (int h = 1; h <= kMaxSrcRectSize; h *= 3) {
1022ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1032ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                const SkIRect srcRect =
1042ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        SkIRect::MakeXYWH((gSurfaceSize - w) / 2, (gSurfaceSize - h) / 2, w, h);
1052ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                canvas->save();
1062ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                switch (random.nextU() % 3) {
1072ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    case 0:
1082ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        canvas->rotate(random.nextF() * 10.f);
1092ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        break;
1102ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    case 1:
1112ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        canvas->rotate(-random.nextF() * 10.f);
1122ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        break;
1132ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    case 2:
1142ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        // rect stays rect
1152ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                        break;
1162ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                }
1179ce9d6772df650ceb0511f275e1a83dffa78ff72reed                canvas->drawImageRect(fImage.get(), srcRect, dstRect, &paint,
1182ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                                      SkCanvas::kFast_SrcRectConstraint);
1192ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                canvas->restore();
1202ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1212ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0);
1222ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                ++rowCount;
1232ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                if ((dstRect.width() + 2 * kPadX) * rowCount > gSize) {
1242ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    canvas->restore();
1252ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY);
1262ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    canvas->save();
1272ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                    rowCount = 0;
1282ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt                }
1292ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt            }
1302ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        }
1312ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt        canvas->restore();
1322ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    }
1332ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1342ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittprivate:
1359ce9d6772df650ceb0511f275e1a83dffa78ff72reed    bool            fAA;
1369ce9d6772df650ceb0511f275e1a83dffa78ff72reed    sk_sp<SkImage>  fImage;
1379ce9d6772df650ceb0511f275e1a83dffa78ff72reed    SkString        fName;
1382ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1392ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt    typedef skiagm::GM INHERITED;
1402ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt};
1412ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualitt
1422ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittDEF_GM( return new DrawMiniBitmapRectGM(true); )
1432ba70995f8a69285dd35968aa3a3e19d5429bdd0joshualittDEF_GM( return new DrawMiniBitmapRectGM(false); )
144