| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 1 |  | 
|  | 2 | /* | 
|  | 3 | * Copyright 2013 Google Inc. | 
|  | 4 | * | 
|  | 5 | * Use of this source code is governed by a BSD-style license that can be | 
|  | 6 | * found in the LICENSE file. | 
|  | 7 | */ | 
|  | 8 | #include "gm.h" | 
|  | 9 | #include "SkBitmap.h" | 
|  | 10 | #include "SkRandom.h" | 
|  | 11 | #include "SkShader.h" | 
|  | 12 | #include "SkXfermode.h" | 
|  | 13 |  | 
|  | 14 | namespace skiagm { | 
|  | 15 |  | 
|  | 16 | /** | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 17 | * Renders overlapping shapes with random SkXfermode::Modes against a checkerboard. | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 18 | */ | 
|  | 19 | class MixedXfermodesGM : public GM { | 
|  | 20 | public: | 
|  | 21 | MixedXfermodesGM() { | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 22 | } | 
|  | 23 |  | 
|  | 24 | protected: | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 25 | virtual SkString onShortName() SK_OVERRIDE { | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 26 | return SkString("mixed_xfermodes"); | 
|  | 27 | } | 
|  | 28 |  | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 29 | virtual SkISize onISize() SK_OVERRIDE { | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 30 | return make_isize(790, 640); | 
|  | 31 | } | 
|  | 32 |  | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 33 | void drawShape(SkCanvas* canvas, | 
|  | 34 | const SkPaint& paint, | 
| commit-bot@chromium.org | e0e7cfe | 2013-09-09 20:09:12 +0000 | [diff] [blame] | 35 | SkRandom* random) { | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 36 | static const SkRect kRect = SkRect::MakeXYWH(SkIntToScalar(-50), SkIntToScalar(-50), | 
|  | 37 | SkIntToScalar(75), SkIntToScalar(105)); | 
|  | 38 | int shape = random->nextULessThan(5); | 
|  | 39 | switch (shape) { | 
|  | 40 | case 0: | 
|  | 41 | canvas->drawCircle(0, 0, 50, paint); | 
|  | 42 | break; | 
|  | 43 | case 1: | 
|  | 44 | canvas->drawRoundRect(kRect, SkIntToScalar(10), SkIntToScalar(20), paint); | 
|  | 45 | break; | 
|  | 46 | case 2: | 
|  | 47 | canvas->drawRect(kRect, paint); | 
|  | 48 | break; | 
|  | 49 | case 3: | 
|  | 50 | if (fConvexPath.isEmpty()) { | 
|  | 51 | SkPoint points[4]; | 
|  | 52 | kRect.toQuad(points); | 
|  | 53 | fConvexPath.moveTo(points[0]); | 
|  | 54 | fConvexPath.quadTo(points[1], points[2]); | 
|  | 55 | fConvexPath.quadTo(points[3], points[0]); | 
|  | 56 | SkASSERT(fConvexPath.isConvex()); | 
|  | 57 | } | 
|  | 58 | canvas->drawPath(fConvexPath, paint); | 
|  | 59 | break; | 
|  | 60 | case 4: | 
|  | 61 | if (fConcavePath.isEmpty()) { | 
|  | 62 | SkPoint points[5] = {{0, SkIntToScalar(-50)} }; | 
|  | 63 | SkMatrix rot; | 
|  | 64 | rot.setRotate(SkIntToScalar(360) / 5); | 
|  | 65 | for (int i = 1; i < 5; ++i) { | 
|  | 66 | rot.mapPoints(points + i, points + i - 1, 1); | 
|  | 67 | } | 
|  | 68 | fConcavePath.moveTo(points[0]); | 
|  | 69 | for (int i = 0; i < 5; ++i) { | 
|  | 70 | fConcavePath.lineTo(points[(2 * i) % 5]); | 
|  | 71 | } | 
|  | 72 | fConcavePath.setFillType(SkPath::kEvenOdd_FillType); | 
|  | 73 | SkASSERT(!fConcavePath.isConvex()); | 
|  | 74 | } | 
|  | 75 | canvas->drawPath(fConcavePath, paint); | 
|  | 76 | break; | 
|  | 77 | } | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { | 
|  | 81 | if (NULL == fBG.get()) { | 
|  | 82 | static uint32_t kCheckerPixelData[] = { 0xFFFFFFFF, | 
|  | 83 | 0xFFCCCCCC, | 
|  | 84 | 0xFFCCCCCC, | 
|  | 85 | 0xFFFFFFFF }; | 
|  | 86 | SkBitmap bitmap; | 
|  | 87 | bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2, 2 * sizeof(uint32_t)); | 
|  | 88 | bitmap.allocPixels(); | 
|  | 89 | bitmap.lockPixels(); | 
|  | 90 | memcpy(bitmap.getPixels(), kCheckerPixelData, sizeof(kCheckerPixelData)); | 
|  | 91 | bitmap.unlockPixels(); | 
|  | 92 | fBG.reset(SkShader::CreateBitmapShader(bitmap, | 
|  | 93 | SkShader::kRepeat_TileMode, | 
|  | 94 | SkShader::kRepeat_TileMode)); | 
|  | 95 | } | 
|  | 96 | SkMatrix lm; | 
|  | 97 | lm.setScale(SkIntToScalar(20), SkIntToScalar(20)); | 
|  | 98 | fBG->setLocalMatrix(lm); | 
|  | 99 |  | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 100 | SkPaint bgPaint; | 
|  | 101 | bgPaint.setShader(fBG.get()); | 
|  | 102 | canvas->drawPaint(bgPaint); | 
|  | 103 | SkISize size = canvas->getDeviceSize(); | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 104 | SkScalar maxScale = SkScalarSqrt((SkIntToScalar(size.fWidth * size.fHeight))) / 300; | 
| commit-bot@chromium.org | e0e7cfe | 2013-09-09 20:09:12 +0000 | [diff] [blame] | 105 | SkRandom random; | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 106 | for (int i = 0; i < kNumShapes; ++i) { | 
|  | 107 | SkScalar s = random.nextRangeScalar(SK_Scalar1 / 8, SK_Scalar1) * maxScale; | 
|  | 108 | SkScalar r = random.nextRangeScalar(0, SkIntToScalar(360)); | 
|  | 109 | SkScalar dx = random.nextRangeScalar(0, SkIntToScalar(size.fWidth)); | 
|  | 110 | SkScalar dy = random.nextRangeScalar(0, SkIntToScalar(size.fHeight)); | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 111 | SkColor color = random.nextU(); | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 112 | SkXfermode::Mode mode = | 
|  | 113 | static_cast<SkXfermode::Mode>(random.nextULessThan(SkXfermode::kLastMode + 1)); | 
| skia.committer@gmail.com | 05a2ee0 | 2013-04-02 07:01:34 +0000 | [diff] [blame] | 114 |  | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 115 | SkPaint p; | 
|  | 116 | p.setAntiAlias(true); | 
|  | 117 | p.setColor(color); | 
|  | 118 | p.setXfermodeMode(mode); | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 119 | canvas->save(); | 
|  | 120 | canvas->translate(dx, dy); | 
|  | 121 | canvas->scale(s, s); | 
|  | 122 | canvas->rotate(r); | 
|  | 123 | this->drawShape(canvas, p, &random); | 
|  | 124 | canvas->restore(); | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 125 | } | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 126 | } | 
|  | 127 |  | 
| vandebo@chromium.org | 0dcbece | 2013-08-20 23:08:40 +0000 | [diff] [blame] | 128 | virtual uint32_t onGetFlags() const { | 
|  | 129 | // Skip PDF rasterization since rendering this PDF takes forever. | 
|  | 130 | return kSkipPDFRasterization_Flag; | 
|  | 131 | } | 
|  | 132 |  | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 133 | private: | 
|  | 134 | enum { | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 135 | kNumShapes = 100, | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 136 | }; | 
|  | 137 | SkAutoTUnref<SkShader> fBG; | 
| bsalomon@google.com | 6db9626 | 2013-05-15 13:10:18 +0000 | [diff] [blame] | 138 | SkPath                 fConcavePath; | 
|  | 139 | SkPath                 fConvexPath; | 
| bsalomon@google.com | 20edf38 | 2013-04-01 18:02:55 +0000 | [diff] [blame] | 140 | typedef GM INHERITED; | 
|  | 141 | }; | 
|  | 142 |  | 
|  | 143 | ////////////////////////////////////////////////////////////////////////////// | 
|  | 144 |  | 
|  | 145 | static GM* MyFactory(void*) { return new MixedXfermodesGM; } | 
|  | 146 | static GMRegistry reg(MyFactory); | 
|  | 147 |  | 
|  | 148 | } |