120edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
220edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com/*
320edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com * Copyright 2013 Google Inc.
420edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com *
520edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
620edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com * found in the LICENSE file.
720edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com */
820edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com#include "gm.h"
920edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com#include "SkBitmap.h"
1020edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com#include "SkRandom.h"
1120edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com#include "SkShader.h"
1220edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com#include "SkXfermode.h"
1320edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
1420edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.comnamespace skiagm {
1520edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
1620edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com/**
176db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com * Renders overlapping shapes with random SkXfermode::Modes against a checkerboard.
1820edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com */
1920edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.comclass MixedXfermodesGM : public GM {
2020edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.compublic:
2120edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    MixedXfermodesGM() {
2220edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    }
2320edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
2420edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.comprotected:
256db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com    virtual SkString onShortName() SK_OVERRIDE {
2620edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com        return SkString("mixed_xfermodes");
2720edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    }
2820edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
296db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com    virtual SkISize onISize() SK_OVERRIDE {
30f539318f0d3dba743ec1886d5d9df0fb1be628a1tfarina        return SkISize::Make(790, 640);
3120edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    }
3220edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
336db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com    void drawShape(SkCanvas* canvas,
346db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                   const SkPaint& paint,
35e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org                   SkRandom* random) {
366db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        static const SkRect kRect = SkRect::MakeXYWH(SkIntToScalar(-50), SkIntToScalar(-50),
376db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                                                     SkIntToScalar(75), SkIntToScalar(105));
386db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        int shape = random->nextULessThan(5);
396db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        switch (shape) {
406db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        case 0:
416db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->drawCircle(0, 0, 50, paint);
426db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            break;
436db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        case 1:
446db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->drawRoundRect(kRect, SkIntToScalar(10), SkIntToScalar(20), paint);
456db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            break;
466db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        case 2:
476db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->drawRect(kRect, paint);
486db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            break;
496db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        case 3:
506db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            if (fConvexPath.isEmpty()) {
516db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                SkPoint points[4];
526db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                kRect.toQuad(points);
536db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                fConvexPath.moveTo(points[0]);
546db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                fConvexPath.quadTo(points[1], points[2]);
556db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                fConvexPath.quadTo(points[3], points[0]);
566db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                SkASSERT(fConvexPath.isConvex());
576db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            }
586db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->drawPath(fConvexPath, paint);
596db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            break;
606db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        case 4:
616db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            if (fConcavePath.isEmpty()) {
626db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                SkPoint points[5] = {{0, SkIntToScalar(-50)} };
636db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                SkMatrix rot;
646db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                rot.setRotate(SkIntToScalar(360) / 5);
656db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                for (int i = 1; i < 5; ++i) {
666db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                    rot.mapPoints(points + i, points + i - 1, 1);
676db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                }
686db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                fConcavePath.moveTo(points[0]);
696db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                for (int i = 0; i < 5; ++i) {
706db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                    fConcavePath.lineTo(points[(2 * i) % 5]);
716db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                }
726db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                fConcavePath.setFillType(SkPath::kEvenOdd_FillType);
736db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                SkASSERT(!fConcavePath.isConvex());
746db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            }
756db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->drawPath(fConcavePath, paint);
766db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            break;
776db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        }
786db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com    }
796db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com
806db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
816db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        if (NULL == fBG.get()) {
826db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            static uint32_t kCheckerPixelData[] = { 0xFFFFFFFF,
836db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                                                    0xFFCCCCCC,
846db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                                                    0xFFCCCCCC,
856db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                                                    0xFFFFFFFF };
866db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            SkBitmap bitmap;
87eb9a46cbbb475e862a084aa2224ec18d4ac5e95breed@google.com            bitmap.allocN32Pixels(2, 2);
886db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            memcpy(bitmap.getPixels(), kCheckerPixelData, sizeof(kCheckerPixelData));
899c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org            SkMatrix lm;
909c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org            lm.setScale(SkIntToScalar(20), SkIntToScalar(20));
916db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            fBG.reset(SkShader::CreateBitmapShader(bitmap,
926db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com                                                   SkShader::kRepeat_TileMode,
939c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                                                   SkShader::kRepeat_TileMode,
949c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                                                   &lm));
956db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        }
966db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com
9720edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com        SkPaint bgPaint;
9820edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com        bgPaint.setShader(fBG.get());
9920edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com        canvas->drawPaint(bgPaint);
10020edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com        SkISize size = canvas->getDeviceSize();
1016db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        SkScalar maxScale = SkScalarSqrt((SkIntToScalar(size.fWidth * size.fHeight))) / 300;
102e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org        SkRandom random;
1036db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        for (int i = 0; i < kNumShapes; ++i) {
1046db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            SkScalar s = random.nextRangeScalar(SK_Scalar1 / 8, SK_Scalar1) * maxScale;
1056db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            SkScalar r = random.nextRangeScalar(0, SkIntToScalar(360));
1066db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            SkScalar dx = random.nextRangeScalar(0, SkIntToScalar(size.fWidth));
1076db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            SkScalar dy = random.nextRangeScalar(0, SkIntToScalar(size.fHeight));
10820edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com            SkColor color = random.nextU();
10920edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com            SkXfermode::Mode mode =
11020edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com                static_cast<SkXfermode::Mode>(random.nextULessThan(SkXfermode::kLastMode + 1));
11105a2ee052c9ef4c781b7b590b00b3d2da3b3449askia.committer@gmail.com
11220edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com            SkPaint p;
11320edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com            p.setAntiAlias(true);
11420edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com            p.setColor(color);
11520edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com            p.setXfermodeMode(mode);
1166db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->save();
1176db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->translate(dx, dy);
1186db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->scale(s, s);
1196db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->rotate(r);
1206db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            this->drawShape(canvas, p, &random);
1216db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com            canvas->restore();
12220edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com        }
12320edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    }
12420edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
1250dcbece326ce2fa1f9046aa69a21bb99de08714avandebo@chromium.org    virtual uint32_t onGetFlags() const {
1260dcbece326ce2fa1f9046aa69a21bb99de08714avandebo@chromium.org        // Skip PDF rasterization since rendering this PDF takes forever.
127a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org        return kSkipPDFRasterization_Flag | kSkipTiled_Flag;
1280dcbece326ce2fa1f9046aa69a21bb99de08714avandebo@chromium.org    }
1290dcbece326ce2fa1f9046aa69a21bb99de08714avandebo@chromium.org
13020edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.comprivate:
13120edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    enum {
1326db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com        kNumShapes = 100,
13320edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    };
13420edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    SkAutoTUnref<SkShader> fBG;
1356db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com    SkPath                 fConcavePath;
1366db962617ff75cadaa6574d85620f7fe0161e23ebsalomon@google.com    SkPath                 fConvexPath;
13720edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com    typedef GM INHERITED;
13820edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com};
13920edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
14020edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com//////////////////////////////////////////////////////////////////////////////
14120edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
14220edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.comstatic GM* MyFactory(void*) { return new MixedXfermodesGM; }
14320edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.comstatic GMRegistry reg(MyFactory);
14420edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com
14520edf38a9ea04b990e0412654e342ced45d3ef15bsalomon@google.com}
146