1 /*
2 * Copyright 2012 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
8 #include "gm/gm.h"
9 #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/SkImage.h"
14 #include "include/core/SkPaint.h"
15 #include "include/core/SkPicture.h"
16 #include "include/core/SkPictureRecorder.h"
17 #include "include/core/SkPoint.h"
18 #include "include/core/SkRect.h"
19 #include "include/core/SkRefCnt.h"
20 #include "include/core/SkScalar.h"
21 #include "include/core/SkShader.h"
22 #include "include/core/SkSize.h"
23 #include "include/core/SkString.h"
24 #include "include/core/SkSurface.h"
25 #include "include/core/SkTileMode.h"
26 #include "include/core/SkTiledImageUtils.h"
27 #include "include/effects/SkGradientShader.h"
28 #include "tools/ToolUtils.h"
29
draw(SkCanvas * canvas,int width,int height,SkColor colors[2])30 static void draw(SkCanvas* canvas, int width, int height, SkColor colors[2]) {
31 const SkPoint center = { SkIntToScalar(width)/2, SkIntToScalar(height)/2 };
32 const SkScalar radius = 40;
33 SkPaint paint;
34 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors, nullptr, 2,
35 SkTileMode::kMirror));
36 paint.setBlendMode(SkBlendMode::kSrc);
37 canvas->drawPaint(paint);
38 }
39
make_raster_image(int width,int height,SkColor colors[2])40 static sk_sp<SkImage> make_raster_image(int width, int height, SkColor colors[2]) {
41 auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(width, height)));
42 draw(surface->getCanvas(), width, height, colors);
43 return surface->makeImageSnapshot();
44 }
45
make_picture_image(int width,int height,SkColor colors[2])46 static sk_sp<SkImage> make_picture_image(int width, int height, SkColor colors[2]) {
47 SkPictureRecorder recorder;
48 draw(recorder.beginRecording(SkRect::MakeIWH(width, height)), width, height, colors);
49 return SkImages::DeferredFromPicture(recorder.finishRecordingAsPicture(),
50 {width, height},
51 nullptr,
52 nullptr,
53 SkImages::BitDepth::kU8,
54 SkColorSpace::MakeSRGB());
55 }
56
57 typedef sk_sp<SkImage> (*ImageMakerProc)(int width, int height, SkColor colors[2]);
58
show_image(SkCanvas * canvas,int width,int height,SkColor colors[2],ImageMakerProc proc,bool manuallyTile)59 static void show_image(SkCanvas* canvas, int width, int height, SkColor colors[2],
60 ImageMakerProc proc, bool manuallyTile) {
61 sk_sp<SkImage> image = proc(width, height, colors);
62 if (!image) {
63 return;
64 }
65
66 SkPaint borderPaint;
67
68 borderPaint.setStyle(SkPaint::kStroke_Style);
69
70 SkRect dstRect = SkRect::MakeWH(128.f, 128.f);
71
72 canvas->save();
73 canvas->clipRect(dstRect);
74 if (manuallyTile) {
75 SkTiledImageUtils::DrawImage(canvas, image, 0, 0);
76 } else {
77 canvas->drawImage(image, 0, 0);
78 }
79 canvas->restore();
80 canvas->drawRect(dstRect, borderPaint);
81
82 dstRect.offset(SkIntToScalar(150), 0);
83 int hw = width / 2;
84 int hh = height / 2;
85 SkRect subset = SkRect::MakeLTRB(hw - 64, hh - 32, hw + 64, hh + 32);
86 if (manuallyTile) {
87 SkTiledImageUtils::DrawImageRect(canvas, image, subset, dstRect, {}, nullptr,
88 SkCanvas::kStrict_SrcRectConstraint);
89 } else {
90 canvas->drawImageRect(image, subset, dstRect, {}, nullptr,
91 SkCanvas::kStrict_SrcRectConstraint);
92 }
93 canvas->drawRect(dstRect, borderPaint);
94
95 dstRect.offset(SkIntToScalar(150), 0);
96 if (manuallyTile) {
97 SkTiledImageUtils::DrawImageRect(canvas, image, dstRect);
98 } else {
99 canvas->drawImageRect(image, dstRect, {});
100 }
101 canvas->drawRect(dstRect, borderPaint);
102 }
103
104 class VeryLargeBitmapGM : public skiagm::GM {
105 ImageMakerProc fProc;
106 const char* fBaseName;
107 bool fManuallyTile;
108
109 public:
VeryLargeBitmapGM(ImageMakerProc proc,const char baseName[],bool manuallyTile)110 VeryLargeBitmapGM(ImageMakerProc proc, const char baseName[], bool manuallyTile)
111 : fProc(proc)
112 , fBaseName(baseName)
113 , fManuallyTile(manuallyTile) {}
114
115 private:
getName() const116 SkString getName() const override {
117 SkString name(fBaseName);
118
119 if (fManuallyTile) {
120 name.append("_manual");
121 }
122
123 return name;
124 }
125
getISize()126 SkISize getISize() override { return {500, 600}; }
127
onDraw(SkCanvas * canvas)128 void onDraw(SkCanvas* canvas) override {
129 int veryBig = 65*1024; // 64K < size
130 int big = 33*1024; // 32K < size < 64K
131 // smaller than many max texture sizes, but large enough to gpu-tile for memory reasons.
132 int medium = 5*1024;
133 int small = 150;
134
135 SkColor colors[2];
136
137 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
138 colors[0] = SK_ColorRED;
139 colors[1] = SK_ColorGREEN;
140 show_image(canvas, small, small, colors, fProc, fManuallyTile);
141 canvas->translate(0, SkIntToScalar(150));
142
143 colors[0] = SK_ColorBLUE;
144 colors[1] = SK_ColorMAGENTA;
145 show_image(canvas, big, small, colors, fProc, fManuallyTile);
146 canvas->translate(0, SkIntToScalar(150));
147
148 colors[0] = SK_ColorMAGENTA;
149 colors[1] = SK_ColorYELLOW;
150 show_image(canvas, medium, medium, colors, fProc, fManuallyTile);
151 canvas->translate(0, SkIntToScalar(150));
152
153 colors[0] = SK_ColorGREEN;
154 colors[1] = SK_ColorYELLOW;
155 // This used to be big enough that we didn't draw on CPU, but now we do.
156 show_image(canvas, veryBig, small, colors, fProc, fManuallyTile);
157 }
158 };
159
160 DEF_GM( return new VeryLargeBitmapGM(make_raster_image, "verylargebitmap",
161 /* manuallyTile= */ false); )
162 DEF_GM( return new VeryLargeBitmapGM(make_raster_image, "verylargebitmap",
163 /* manuallyTile= */ true); )
164 DEF_GM( return new VeryLargeBitmapGM(make_picture_image, "verylarge_picture_image",
165 /* manuallyTile= */ false); )
166 DEF_GM( return new VeryLargeBitmapGM(make_picture_image, "verylarge_picture_image",
167 /* manuallyTile= */ true); )
168