blob: ce6c22ad3fd4575e398c321f1438c46751692ce5 [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 */
Ben Wagner7fde8e12019-05-01 17:28:53 -04007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkBlendMode.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkColor.h"
12#include "include/core/SkColorSpace.h"
13#include "include/core/SkFont.h"
14#include "include/core/SkImageInfo.h"
15#include "include/core/SkMatrix.h"
16#include "include/core/SkPaint.h"
Mike Reed06d7c9d2020-08-26 12:56:51 -040017#include "include/core/SkPathBuilder.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040018#include "include/core/SkPoint.h"
19#include "include/core/SkRect.h"
20#include "include/core/SkRefCnt.h"
21#include "include/core/SkScalar.h"
22#include "include/core/SkSize.h"
23#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/core/SkSurface.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040025#include "include/core/SkTypeface.h"
26#include "include/core/SkTypes.h"
Kevin Lubick0d4d1142023-02-13 09:13:10 -050027#include "src/base/SkRandom.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "tools/ToolUtils.h"
Kevin Lubicke836c3a2023-10-20 06:55:35 -040029#include "tools/fonts/FontToolUtils.h"
joshualitt5ce33c12015-01-28 11:08:00 -080030
31namespace skiagm {
32
33/**
34 * Renders overlapping shapes with colorburn against a checkerboard.
35 */
36class DstReadShuffle : public GM {
37public:
Brian Salomond02b6f32017-03-17 10:41:39 -040038 DstReadShuffle() { this->setBGColor(kBackground); }
joshualitt5ce33c12015-01-28 11:08:00 -080039
40protected:
41 enum ShapeType {
42 kCircle_ShapeType,
43 kRoundRect_ShapeType,
44 kRect_ShapeType,
45 kConvexPath_ShapeType,
46 kConcavePath_ShapeType,
47 kText_ShapeType,
48 kNumShapeTypes
49 };
50
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000051 SkString getName() const override { return SkString("dstreadshuffle"); }
joshualitt5ce33c12015-01-28 11:08:00 -080052
Leandro Lovisolo8f023882023-08-15 21:13:52 +000053 SkISize getISize() override { return SkISize::Make(530, 680); }
joshualitt5ce33c12015-01-28 11:08:00 -080054
Brian Salomon8336e942017-03-15 15:37:43 -040055 void drawShape(SkCanvas* canvas, SkPaint* paint, ShapeType type) {
56 const SkRect kRect = SkRect::MakeXYWH(0, 0, 75.f, 85.f);
joshualitt5ce33c12015-01-28 11:08:00 -080057 switch (type) {
58 case kCircle_ShapeType:
Brian Salomon8336e942017-03-15 15:37:43 -040059 canvas->drawCircle(kRect.centerX(), kRect.centerY(), kRect.width() / 2.f, *paint);
joshualitt5ce33c12015-01-28 11:08:00 -080060 break;
61 case kRoundRect_ShapeType:
Brian Salomon8336e942017-03-15 15:37:43 -040062 canvas->drawRoundRect(kRect, 15.f, 15.f, *paint);
joshualitt5ce33c12015-01-28 11:08:00 -080063 break;
64 case kRect_ShapeType:
65 canvas->drawRect(kRect, *paint);
66 break;
67 case kConvexPath_ShapeType:
68 if (fConvexPath.isEmpty()) {
69 SkPoint points[4];
70 kRect.toQuad(points);
Mike Reed06d7c9d2020-08-26 12:56:51 -040071 fConvexPath = SkPathBuilder().moveTo(points[0])
72 .quadTo(points[1], points[2])
73 .quadTo(points[3], points[0])
74 .detach();
joshualitt5ce33c12015-01-28 11:08:00 -080075 SkASSERT(fConvexPath.isConvex());
76 }
77 canvas->drawPath(fConvexPath, *paint);
78 break;
79 case kConcavePath_ShapeType:
80 if (fConcavePath.isEmpty()) {
Mike Reed06d7c9d2020-08-26 12:56:51 -040081 SkPathBuilder b;
Brian Salomon8336e942017-03-15 15:37:43 -040082 SkPoint points[5] = {{50.f, 0.f}};
joshualitt5ce33c12015-01-28 11:08:00 -080083 SkMatrix rot;
Brian Salomon8336e942017-03-15 15:37:43 -040084 rot.setRotate(360.f / 5, 50.f, 70.f);
joshualitt5ce33c12015-01-28 11:08:00 -080085 for (int i = 1; i < 5; ++i) {
86 rot.mapPoints(points + i, points + i - 1, 1);
87 }
Mike Reed06d7c9d2020-08-26 12:56:51 -040088 b.moveTo(points[0]);
joshualitt5ce33c12015-01-28 11:08:00 -080089 for (int i = 0; i < 5; ++i) {
Mike Reed06d7c9d2020-08-26 12:56:51 -040090 b.lineTo(points[(2 * i) % 5]);
joshualitt5ce33c12015-01-28 11:08:00 -080091 }
Mike Reed06d7c9d2020-08-26 12:56:51 -040092 fConcavePath = b.setFillType(SkPathFillType::kEvenOdd)
93 .detach();
joshualitt5ce33c12015-01-28 11:08:00 -080094 SkASSERT(!fConcavePath.isConvex());
95 }
96 canvas->drawPath(fConcavePath, *paint);
97 break;
98 case kText_ShapeType: {
Brian Salomon8336e942017-03-15 15:37:43 -040099 const char* text = "N";
Kevin Lubicke836c3a2023-10-20 06:55:35 -0400100 SkFont font(ToolUtils::DefaultPortableTypeface(), 100);
Hal Canary6ac0df82019-01-07 16:01:22 -0500101 font.setEmbolden(true);
102 canvas->drawString(text, 0.f, 100.f, font, *paint);
John Stiles30212b72020-06-11 17:55:07 -0400103 break;
joshualitt5ce33c12015-01-28 11:08:00 -0800104 }
105 default:
106 break;
107 }
108 }
109
Brian Salomon8336e942017-03-15 15:37:43 -0400110 static SkColor GetColor(SkRandom* random) {
Mike Kleinea3f0142019-03-20 11:12:10 -0500111 SkColor color = ToolUtils::color_to_565(random->nextU() | 0xFF000000);
Brian Salomon8336e942017-03-15 15:37:43 -0400112 return SkColorSetA(color, 0x80);
joshualitt5ce33c12015-01-28 11:08:00 -0800113 }
114
Brian Salomon8336e942017-03-15 15:37:43 -0400115 static void DrawHairlines(SkCanvas* canvas) {
Brian Salomond02b6f32017-03-17 10:41:39 -0400116 if (canvas->imageInfo().alphaType() == kOpaque_SkAlphaType) {
117 canvas->clear(kBackground);
118 } else {
119 canvas->clear(SK_ColorTRANSPARENT);
120 }
Brian Salomon8336e942017-03-15 15:37:43 -0400121 SkPaint hairPaint;
122 hairPaint.setStyle(SkPaint::kStroke_Style);
123 hairPaint.setStrokeWidth(0);
124 hairPaint.setAntiAlias(true);
125 static constexpr int kNumHairlines = 12;
126 SkPoint pts[] = {{3.f, 7.f}, {29.f, 7.f}};
127 SkRandom colorRandom;
128 SkMatrix rot;
129 rot.setRotate(360.f / kNumHairlines, 15.5f, 12.f);
130 rot.postTranslate(3.f, 0);
131 for (int i = 0; i < 12; ++i) {
132 hairPaint.setColor(GetColor(&colorRandom));
Hal Canary23e474c2017-05-15 13:35:35 -0400133 canvas->drawLine(pts[0], pts[1], hairPaint);
Brian Salomon8336e942017-03-15 15:37:43 -0400134 rot.mapPoints(pts, 2);
joshualitt5ce33c12015-01-28 11:08:00 -0800135 }
136 }
137
mtklein36352bf2015-03-25 18:17:31 -0700138 void onDraw(SkCanvas* canvas) override {
Brian Salomon8336e942017-03-15 15:37:43 -0400139 SkScalar y = 5;
joshualitt5ce33c12015-01-28 11:08:00 -0800140 for (int i = 0; i < kNumShapeTypes; i++) {
Brian Salomon8336e942017-03-15 15:37:43 -0400141 SkRandom colorRandom;
joshualitt5ce33c12015-01-28 11:08:00 -0800142 ShapeType shapeType = static_cast<ShapeType>(i);
Brian Salomon8336e942017-03-15 15:37:43 -0400143 SkScalar x = 5;
144 for (int r = 0; r <= 15; r++) {
145 SkPaint p;
146 p.setAntiAlias(true);
147 p.setColor(GetColor(&colorRandom));
148 // In order to get some op combining on the GPU backend we do 2 src over
149 // for each xfer mode which requires a dst read
150 p.setBlendMode(r % 3 == 0 ? SkBlendMode::kColorBurn : SkBlendMode::kSrcOver);
151 canvas->save();
152 canvas->translate(x, y);
153 this->drawShape(canvas, &p, shapeType);
154 canvas->restore();
155 x += 15;
joshualitt5ce33c12015-01-28 11:08:00 -0800156 }
Brian Salomon8336e942017-03-15 15:37:43 -0400157 y += 110;
joshualitt5ce33c12015-01-28 11:08:00 -0800158 }
Brian Salomon8336e942017-03-15 15:37:43 -0400159 // Draw hairlines to a surface and then draw that to the main canvas with a zoom so that
160 // it is easier to see how they blend.
161 SkImageInfo info;
Brian Salomond02b6f32017-03-17 10:41:39 -0400162 // Recording canvases don't have a color type.
163 if (SkColorType::kUnknown_SkColorType == canvas->imageInfo().colorType()) {
164 info = SkImageInfo::MakeN32Premul(35, 35);
165 } else {
Brian Salomon8336e942017-03-15 15:37:43 -0400166 info = SkImageInfo::Make(35, 35,
167 canvas->imageInfo().colorType(),
168 canvas->imageInfo().alphaType(),
169 canvas->imageInfo().refColorSpace());
Brian Salomon8336e942017-03-15 15:37:43 -0400170 }
171 auto surf = canvas->makeSurface(info);
Cary Clarka24712e2018-09-05 18:41:40 +0000172 if (!surf) {
173 // Fall back to raster. Raster supports only one of the 8 bit per-channel RGBA or BGRA
174 // formats. This fall back happens when running with --preAbandonGpuContext.
175 if ((info.colorType() == kRGBA_8888_SkColorType ||
176 info.colorType() == kBGRA_8888_SkColorType) &&
177 info.colorType() != kN32_SkColorType) {
178 info = SkImageInfo::Make(35, 35,
179 kN32_SkColorType,
180 canvas->imageInfo().alphaType(),
181 canvas->imageInfo().refColorSpace());
182 }
Kevin Lubick5c93acf2023-05-09 12:11:43 -0400183 surf = SkSurfaces::Raster(info);
Cary Clarka24712e2018-09-05 18:41:40 +0000184 SkASSERT(surf);
185 }
Brian Salomon8336e942017-03-15 15:37:43 -0400186 canvas->scale(5.f, 5.f);
187 canvas->translate(67.f, 10.f);
188 DrawHairlines(surf->getCanvas());
189 canvas->drawImage(surf->makeImageSnapshot(), 0.f, 0.f);
joshualitt5ce33c12015-01-28 11:08:00 -0800190 }
191
192private:
Brian Salomond02b6f32017-03-17 10:41:39 -0400193 static constexpr SkColor kBackground = SK_ColorLTGRAY;
Brian Salomon8336e942017-03-15 15:37:43 -0400194 SkPath fConcavePath;
195 SkPath fConvexPath;
John Stiles7571f9e2020-09-02 22:42:33 -0400196 using INHERITED = GM;
joshualitt5ce33c12015-01-28 11:08:00 -0800197};
198
199//////////////////////////////////////////////////////////////////////////////
200
Hal Canarye964c182019-01-23 10:22:01 -0500201DEF_GM( return new DstReadShuffle; )
joshualitt5ce33c12015-01-28 11:08:00 -0800202
John Stilesa6841be2020-08-06 14:11:56 -0400203} // namespace skiagm