1 /*
2 * Copyright 2015 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/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkColorSpace.h"
12 #include "include/core/SkData.h"
13 #include "include/core/SkEncodedImageFormat.h"
14 #include "include/core/SkImage.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkMatrix.h"
17 #include "include/core/SkPaint.h"
18 #include "include/core/SkPicture.h"
19 #include "include/core/SkPictureRecorder.h"
20 #include "include/core/SkRect.h"
21 #include "include/core/SkRefCnt.h"
22 #include "include/core/SkShader.h"
23 #include "include/core/SkSize.h"
24 #include "include/core/SkString.h"
25 #include "include/core/SkSurface.h"
26 #include "include/core/SkTileMode.h"
27 #include "include/core/SkTypes.h"
28
29 #include <utility>
30
draw_something(SkCanvas * canvas,const SkRect & bounds)31 static void draw_something(SkCanvas* canvas, const SkRect& bounds) {
32 SkPaint paint;
33 paint.setAntiAlias(true);
34 paint.setColor(SK_ColorRED);
35 paint.setStyle(SkPaint::kStroke_Style);
36 paint.setStrokeWidth(10);
37 canvas->drawRect(bounds, paint);
38 paint.setStyle(SkPaint::kFill_Style);
39 paint.setColor(SK_ColorBLUE);
40 canvas->drawOval(bounds, paint);
41 }
42
43 typedef sk_sp<SkImage> (*ImageMakerProc)(GrRecordingContext*, SkPicture*, const SkImageInfo&);
44
make_raster(GrRecordingContext *,SkPicture * pic,const SkImageInfo & info)45 static sk_sp<SkImage> make_raster(GrRecordingContext*,
46 SkPicture* pic,
47 const SkImageInfo& info) {
48 auto surface(SkSurface::MakeRaster(info));
49 surface->getCanvas()->clear(0);
50 surface->getCanvas()->drawPicture(pic);
51 return surface->makeImageSnapshot();
52 }
53
make_texture(GrRecordingContext * ctx,SkPicture * pic,const SkImageInfo & info)54 static sk_sp<SkImage> make_texture(GrRecordingContext* ctx,
55 SkPicture* pic,
56 const SkImageInfo& info) {
57 if (!ctx) {
58 return nullptr;
59 }
60 auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info));
61 if (!surface) {
62 return nullptr;
63 }
64 surface->getCanvas()->clear(0);
65 surface->getCanvas()->drawPicture(pic);
66 return surface->makeImageSnapshot();
67 }
68
make_pict_gen(GrRecordingContext *,SkPicture * pic,const SkImageInfo & info)69 static sk_sp<SkImage> make_pict_gen(GrRecordingContext*,
70 SkPicture* pic,
71 const SkImageInfo& info) {
72 return SkImage::MakeFromPicture(sk_ref_sp(pic), info.dimensions(), nullptr, nullptr,
73 SkImage::BitDepth::kU8,
74 SkColorSpace::MakeSRGB());
75 }
76
make_encode_gen(GrRecordingContext * ctx,SkPicture * pic,const SkImageInfo & info)77 static sk_sp<SkImage> make_encode_gen(GrRecordingContext* ctx,
78 SkPicture* pic,
79 const SkImageInfo& info) {
80 sk_sp<SkImage> src(make_raster(ctx, pic, info));
81 if (!src) {
82 return nullptr;
83 }
84 sk_sp<SkData> encoded = src->encodeToData(SkEncodedImageFormat::kPNG, 100);
85 if (!encoded) {
86 return nullptr;
87 }
88 return SkImage::MakeFromEncoded(std::move(encoded));
89 }
90
91 const ImageMakerProc gProcs[] = {
92 make_raster,
93 make_texture,
94 make_pict_gen,
95 make_encode_gen,
96 };
97
98 /*
99 * Exercise drawing pictures inside an image, showing that the image version is pixelated
100 * (correctly) when it is inside an image.
101 */
102 class ImageShaderGM : public skiagm::GM {
103 sk_sp<SkPicture> fPicture;
104
105 public:
ImageShaderGM()106 ImageShaderGM() {}
107
108 protected:
onShortName()109 SkString onShortName() override {
110 return SkString("image-shader");
111 }
112
onISize()113 SkISize onISize() override {
114 return SkISize::Make(850, 450);
115 }
116
onOnceBeforeDraw()117 void onOnceBeforeDraw() override {
118 const SkRect bounds = SkRect::MakeWH(100, 100);
119 SkPictureRecorder recorder;
120 draw_something(recorder.beginRecording(bounds), bounds);
121 fPicture = recorder.finishRecordingAsPicture();
122 }
123
testImage(SkCanvas * canvas,SkImage * image)124 void testImage(SkCanvas* canvas, SkImage* image) {
125 SkAutoCanvasRestore acr(canvas, true);
126
127 canvas->drawImage(image, 0, 0);
128 canvas->translate(0, 120);
129
130 const SkTileMode tile = SkTileMode::kRepeat;
131 const SkMatrix localM = SkMatrix::Translate(-50, -50);
132 SkPaint paint;
133 paint.setShader(image->makeShader(tile, tile, &localM));
134 paint.setAntiAlias(true);
135 canvas->drawCircle(50, 50, 50, paint);
136 }
137
onDraw(SkCanvas * canvas)138 void onDraw(SkCanvas* canvas) override {
139 canvas->translate(20, 20);
140
141 const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
142
143 for (size_t i = 0; i < SK_ARRAY_COUNT(gProcs); ++i) {
144 sk_sp<SkImage> image(gProcs[i](canvas->recordingContext(), fPicture.get(), info));
145 if (image) {
146 this->testImage(canvas, image.get());
147 }
148 canvas->translate(120, 0);
149 }
150 }
151
152 private:
153 using INHERITED = skiagm::GM;
154 };
155 DEF_GM( return new ImageShaderGM; )
156