blob: aea71ec6b1e89c0c96eab3f31e225556140f39c1 [file] [log] [blame]
joshualitt5ce33c12015-01-28 11:08:00 -08001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#include "gm.h"
8#include "SkBitmap.h"
bungemand3ebb482015-08-05 13:57:49 -07009#include "SkPath.h"
joshualitt5ce33c12015-01-28 11:08:00 -080010#include "SkRandom.h"
11#include "SkShader.h"
Brian Salomon8336e942017-03-15 15:37:43 -040012#include "SkSurface.h"
joshualitt5ce33c12015-01-28 11:08:00 -080013
14namespace skiagm {
15
16/**
17 * Renders overlapping shapes with colorburn against a checkerboard.
18 */
19class DstReadShuffle : public GM {
20public:
Brian Salomon8336e942017-03-15 15:37:43 -040021 DstReadShuffle() { this->setBGColor(SK_ColorLTGRAY); }
joshualitt5ce33c12015-01-28 11:08:00 -080022
23protected:
24 enum ShapeType {
25 kCircle_ShapeType,
26 kRoundRect_ShapeType,
27 kRect_ShapeType,
28 kConvexPath_ShapeType,
29 kConcavePath_ShapeType,
30 kText_ShapeType,
31 kNumShapeTypes
32 };
33
mtklein36352bf2015-03-25 18:17:31 -070034 SkString onShortName() override {
joshualitt5ce33c12015-01-28 11:08:00 -080035 return SkString("dstreadshuffle");
36 }
37
mtklein36352bf2015-03-25 18:17:31 -070038 SkISize onISize() override {
Brian Salomon8336e942017-03-15 15:37:43 -040039 return SkISize::Make(530, 680);
joshualitt5ce33c12015-01-28 11:08:00 -080040 }
41
Brian Salomon8336e942017-03-15 15:37:43 -040042 void drawShape(SkCanvas* canvas, SkPaint* paint, ShapeType type) {
43 const SkRect kRect = SkRect::MakeXYWH(0, 0, 75.f, 85.f);
joshualitt5ce33c12015-01-28 11:08:00 -080044 switch (type) {
45 case kCircle_ShapeType:
Brian Salomon8336e942017-03-15 15:37:43 -040046 canvas->drawCircle(kRect.centerX(), kRect.centerY(), kRect.width() / 2.f, *paint);
joshualitt5ce33c12015-01-28 11:08:00 -080047 break;
48 case kRoundRect_ShapeType:
Brian Salomon8336e942017-03-15 15:37:43 -040049 canvas->drawRoundRect(kRect, 15.f, 15.f, *paint);
joshualitt5ce33c12015-01-28 11:08:00 -080050 break;
51 case kRect_ShapeType:
52 canvas->drawRect(kRect, *paint);
53 break;
54 case kConvexPath_ShapeType:
55 if (fConvexPath.isEmpty()) {
56 SkPoint points[4];
57 kRect.toQuad(points);
58 fConvexPath.moveTo(points[0]);
59 fConvexPath.quadTo(points[1], points[2]);
60 fConvexPath.quadTo(points[3], points[0]);
61 SkASSERT(fConvexPath.isConvex());
62 }
63 canvas->drawPath(fConvexPath, *paint);
64 break;
65 case kConcavePath_ShapeType:
66 if (fConcavePath.isEmpty()) {
Brian Salomon8336e942017-03-15 15:37:43 -040067 SkPoint points[5] = {{50.f, 0.f}};
joshualitt5ce33c12015-01-28 11:08:00 -080068 SkMatrix rot;
Brian Salomon8336e942017-03-15 15:37:43 -040069 rot.setRotate(360.f / 5, 50.f, 70.f);
joshualitt5ce33c12015-01-28 11:08:00 -080070 for (int i = 1; i < 5; ++i) {
71 rot.mapPoints(points + i, points + i - 1, 1);
72 }
73 fConcavePath.moveTo(points[0]);
74 for (int i = 0; i < 5; ++i) {
75 fConcavePath.lineTo(points[(2 * i) % 5]);
76 }
77 fConcavePath.setFillType(SkPath::kEvenOdd_FillType);
78 SkASSERT(!fConcavePath.isConvex());
79 }
80 canvas->drawPath(fConcavePath, *paint);
81 break;
82 case kText_ShapeType: {
Brian Salomon8336e942017-03-15 15:37:43 -040083 const char* text = "N";
84 paint->setTextSize(100.f);
85 paint->setFakeBoldText(true);
caryclarkf1f8bd52015-07-29 06:58:40 -070086 sk_tool_utils::set_portable_typeface(paint);
Brian Salomon8336e942017-03-15 15:37:43 -040087 canvas->drawText(text, strlen(text), 0.f, 100.f, *paint);
joshualitt5ce33c12015-01-28 11:08:00 -080088 }
89 default:
90 break;
91 }
92 }
93
Brian Salomon8336e942017-03-15 15:37:43 -040094 static SkColor GetColor(SkRandom* random) {
95 SkColor color = sk_tool_utils::color_to_565(random->nextU() | 0xFF000000);
96 return SkColorSetA(color, 0x80);
joshualitt5ce33c12015-01-28 11:08:00 -080097 }
98
Brian Salomon8336e942017-03-15 15:37:43 -040099 static void DrawHairlines(SkCanvas* canvas) {
100 canvas->clear(SK_ColorTRANSPARENT);
101 SkPaint hairPaint;
102 hairPaint.setStyle(SkPaint::kStroke_Style);
103 hairPaint.setStrokeWidth(0);
104 hairPaint.setAntiAlias(true);
105 static constexpr int kNumHairlines = 12;
106 SkPoint pts[] = {{3.f, 7.f}, {29.f, 7.f}};
107 SkRandom colorRandom;
108 SkMatrix rot;
109 rot.setRotate(360.f / kNumHairlines, 15.5f, 12.f);
110 rot.postTranslate(3.f, 0);
111 for (int i = 0; i < 12; ++i) {
112 hairPaint.setColor(GetColor(&colorRandom));
113 canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, hairPaint);
114 rot.mapPoints(pts, 2);
joshualitt5ce33c12015-01-28 11:08:00 -0800115 }
116 }
117
mtklein36352bf2015-03-25 18:17:31 -0700118 void onDraw(SkCanvas* canvas) override {
Brian Salomon8336e942017-03-15 15:37:43 -0400119 SkScalar y = 5;
joshualitt5ce33c12015-01-28 11:08:00 -0800120 for (int i = 0; i < kNumShapeTypes; i++) {
Brian Salomon8336e942017-03-15 15:37:43 -0400121 SkRandom colorRandom;
joshualitt5ce33c12015-01-28 11:08:00 -0800122 ShapeType shapeType = static_cast<ShapeType>(i);
Brian Salomon8336e942017-03-15 15:37:43 -0400123 SkScalar x = 5;
124 for (int r = 0; r <= 15; r++) {
125 SkPaint p;
126 p.setAntiAlias(true);
127 p.setColor(GetColor(&colorRandom));
128 // In order to get some op combining on the GPU backend we do 2 src over
129 // for each xfer mode which requires a dst read
130 p.setBlendMode(r % 3 == 0 ? SkBlendMode::kColorBurn : SkBlendMode::kSrcOver);
131 canvas->save();
132 canvas->translate(x, y);
133 this->drawShape(canvas, &p, shapeType);
134 canvas->restore();
135 x += 15;
joshualitt5ce33c12015-01-28 11:08:00 -0800136 }
Brian Salomon8336e942017-03-15 15:37:43 -0400137 y += 110;
joshualitt5ce33c12015-01-28 11:08:00 -0800138 }
Brian Salomon8336e942017-03-15 15:37:43 -0400139 // Draw hairlines to a surface and then draw that to the main canvas with a zoom so that
140 // it is easier to see how they blend.
141 SkImageInfo info;
142 if (SkColorType::kUnknown_SkColorType != canvas->imageInfo().colorType()) {
143 info = SkImageInfo::Make(35, 35,
144 canvas->imageInfo().colorType(),
145 canvas->imageInfo().alphaType(),
146 canvas->imageInfo().refColorSpace());
147 } else {
148 info = SkImageInfo::MakeN32Premul(35, 35);
149 }
150 auto surf = canvas->makeSurface(info);
151 if (!surf) {
152 surf = SkSurface::MakeRaster(info);
153 }
154 canvas->scale(5.f, 5.f);
155 canvas->translate(67.f, 10.f);
156 DrawHairlines(surf->getCanvas());
157 canvas->drawImage(surf->makeImageSnapshot(), 0.f, 0.f);
joshualitt5ce33c12015-01-28 11:08:00 -0800158 }
159
160private:
Brian Salomon8336e942017-03-15 15:37:43 -0400161 SkPath fConcavePath;
162 SkPath fConvexPath;
joshualitt5ce33c12015-01-28 11:08:00 -0800163 typedef GM INHERITED;
164};
165
166//////////////////////////////////////////////////////////////////////////////
167
168static GM* MyFactory(void*) { return new DstReadShuffle; }
169static GMRegistry reg(MyFactory);
170
171}