• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 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 <functional>
9 #include "gm.h"
10 #include "sk_tool_utils.h"
11 #include "SkAutoPixmapStorage.h"
12 #include "SkData.h"
13 #include "SkCanvas.h"
14 #include "SkRandom.h"
15 #include "SkStream.h"
16 #include "SkSurface.h"
17 
18 #if SK_SUPPORT_GPU
19 #include "GrContext.h"
20 #endif
21 
drawJpeg(SkCanvas * canvas,const SkISize & size)22 static void drawJpeg(SkCanvas* canvas, const SkISize& size) {
23     // TODO: Make this draw a file that is checked in, so it can
24     // be exercised on machines other than mike's. Will require a
25     // rebaseline.
26     sk_sp<SkData> data(SkData::MakeFromFileName("/Users/mike/Downloads/skia.google.jpeg"));
27     if (nullptr == data) {
28         return;
29     }
30     sk_sp<SkImage> image = SkImage::MakeFromEncoded(std::move(data));
31     if (image) {
32         SkAutoCanvasRestore acr(canvas, true);
33         canvas->scale(size.width() * 1.0f / image->width(),
34                       size.height() * 1.0f / image->height());
35         canvas->drawImage(image, 0, 0, nullptr);
36     }
37 }
38 
drawContents(SkSurface * surface,SkColor fillC)39 static void drawContents(SkSurface* surface, SkColor fillC) {
40     SkSize size = SkSize::Make(SkIntToScalar(surface->width()),
41                                SkIntToScalar(surface->height()));
42     SkCanvas* canvas = surface->getCanvas();
43 
44     SkScalar stroke = size.fWidth / 10;
45     SkScalar radius = (size.fWidth - stroke) / 2;
46 
47     SkPaint paint;
48 
49     paint.setAntiAlias(true);
50     paint.setColor(fillC);
51     canvas->drawCircle(size.fWidth/2, size.fHeight/2, radius, paint);
52 
53     paint.setStyle(SkPaint::kStroke_Style);
54     paint.setStrokeWidth(stroke);
55     paint.setColor(SK_ColorBLACK);
56     canvas->drawCircle(size.fWidth/2, size.fHeight/2, radius, paint);
57 }
58 
test_surface(SkCanvas * canvas,SkSurface * surf,bool usePaint)59 static void test_surface(SkCanvas* canvas, SkSurface* surf, bool usePaint) {
60     drawContents(surf, SK_ColorRED);
61     sk_sp<SkImage> imgR = surf->makeImageSnapshot();
62 
63     if (true) {
64         sk_sp<SkImage> imgR2 = surf->makeImageSnapshot();
65         SkASSERT(imgR == imgR2);
66     }
67 
68     drawContents(surf, SK_ColorGREEN);
69     sk_sp<SkImage> imgG = surf->makeImageSnapshot();
70 
71     // since we've drawn after we snapped imgR, imgG will be a different obj
72     SkASSERT(imgR != imgG);
73 
74     drawContents(surf, SK_ColorBLUE);
75 
76     SkPaint paint;
77 //    paint.setFilterBitmap(true);
78 //    paint.setAlpha(0x80);
79 
80     canvas->drawImage(imgR, 0, 0, usePaint ? &paint : nullptr);
81     canvas->drawImage(imgG, 0, 80, usePaint ? &paint : nullptr);
82     surf->draw(canvas, 0, 160, usePaint ? &paint : nullptr);
83 
84     SkRect src1, src2, src3;
85     src1.iset(0, 0, surf->width(), surf->height());
86     src2.iset(-surf->width() / 2, -surf->height() / 2,
87              surf->width(), surf->height());
88     src3.iset(0, 0, surf->width() / 2, surf->height() / 2);
89 
90     SkRect dst1, dst2, dst3, dst4;
91     dst1.set(0, 240, 65, 305);
92     dst2.set(0, 320, 65, 385);
93     dst3.set(0, 400, 65, 465);
94     dst4.set(0, 480, 65, 545);
95 
96     canvas->drawImageRect(imgR, src1, dst1, usePaint ? &paint : nullptr);
97     canvas->drawImageRect(imgG, src2, dst2, usePaint ? &paint : nullptr);
98     canvas->drawImageRect(imgR, src3, dst3, usePaint ? &paint : nullptr);
99     canvas->drawImageRect(imgG, dst4, usePaint ? &paint : nullptr);
100 }
101 
102 class ImageGM : public skiagm::GM {
103     void*   fBuffer;
104     size_t  fBufferSize;
105     SkSize  fSize;
106     enum {
107         W = 64,
108         H = 64,
109         RB = W * 4 + 8,
110     };
111 public:
ImageGM()112     ImageGM() {
113         fBufferSize = RB * H;
114         fBuffer = sk_malloc_throw(fBufferSize);
115         fSize.set(SkIntToScalar(W), SkIntToScalar(H));
116     }
117 
~ImageGM()118     ~ImageGM() override {
119         sk_free(fBuffer);
120     }
121 
122 protected:
onShortName()123     SkString onShortName() override {
124         return SkString("image-surface");
125     }
126 
onISize()127     SkISize onISize() override {
128         return SkISize::Make(960, 1200);
129     }
130 
onDraw(SkCanvas * canvas)131     void onDraw(SkCanvas* canvas) override {
132         drawJpeg(canvas, this->getISize());
133 
134         canvas->scale(2, 2);
135 
136         const char* kLabel1 = "Original Img";
137         const char* kLabel2 = "Modified Img";
138         const char* kLabel3 = "Cur Surface";
139         const char* kLabel4 = "Full Crop";
140         const char* kLabel5 = "Over-crop";
141         const char* kLabel6 = "Upper-left";
142         const char* kLabel7 = "No Crop";
143 
144         const char* kLabel8 = "Pre-Alloc Img";
145         const char* kLabel9 = "New Alloc Img";
146         const char* kLabel10 = "GPU";
147 
148         SkPaint textPaint;
149         textPaint.setAntiAlias(true);
150         sk_tool_utils::set_portable_typeface(&textPaint);
151         textPaint.setTextSize(8);
152 
153         canvas->drawString(kLabel1, 10,  60, textPaint);
154         canvas->drawString(kLabel2, 10, 140, textPaint);
155         canvas->drawString(kLabel3, 10, 220, textPaint);
156         canvas->drawString(kLabel4, 10, 300, textPaint);
157         canvas->drawString(kLabel5, 10, 380, textPaint);
158         canvas->drawString(kLabel6, 10, 460, textPaint);
159         canvas->drawString(kLabel7, 10, 540, textPaint);
160 
161         canvas->drawString(kLabel8, 80, 10, textPaint);
162         canvas->drawString(kLabel9, 160, 10, textPaint);
163         canvas->drawString(kLabel10, 265, 10, textPaint);
164 
165         canvas->translate(80, 20);
166 
167         // since we draw into this directly, we need to start fresh
168         sk_bzero(fBuffer, fBufferSize);
169 
170         SkImageInfo info = SkImageInfo::MakeN32Premul(W, H);
171         sk_sp<SkSurface> surf0(SkSurface::MakeRasterDirect(info, fBuffer, RB));
172         sk_sp<SkSurface> surf1(SkSurface::MakeRaster(info));
173         sk_sp<SkSurface> surf2;  // gpu
174 
175 #if SK_SUPPORT_GPU
176         surf2 = SkSurface::MakeRenderTarget(canvas->getGrContext(), SkBudgeted::kNo, info);
177 #endif
178 
179         test_surface(canvas, surf0.get(), true);
180         canvas->translate(80, 0);
181         test_surface(canvas, surf1.get(), true);
182         if (surf2) {
183             canvas->translate(80, 0);
184             test_surface(canvas, surf2.get(), true);
185         }
186     }
187 
188 private:
189     typedef skiagm::GM INHERITED;
190 };
DEF_GM(return new ImageGM;)191 DEF_GM( return new ImageGM; )
192 
193 ///////////////////////////////////////////////////////////////////////////////////////////////////
194 
195 #include "SkPictureRecorder.h"
196 
197 static void draw_pixmap(SkCanvas* canvas, const SkPixmap& pmap) {
198     SkBitmap bitmap;
199     bitmap.installPixels(pmap);
200     canvas->drawBitmap(bitmap, 0, 0, nullptr);
201 }
202 
show_scaled_pixels(SkCanvas * canvas,SkImage * image)203 static void show_scaled_pixels(SkCanvas* canvas, SkImage* image) {
204     SkAutoCanvasRestore acr(canvas, true);
205 
206     canvas->drawImage(image, 0, 0, nullptr);
207     canvas->translate(110, 10);
208 
209     const SkImageInfo info = SkImageInfo::MakeN32Premul(40, 40);
210     SkAutoPixmapStorage storage;
211     storage.alloc(info);
212 
213     const SkImage::CachingHint chints[] = {
214         SkImage::kAllow_CachingHint, SkImage::kDisallow_CachingHint,
215     };
216     const SkFilterQuality qualities[] = {
217         kNone_SkFilterQuality, kLow_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality,
218     };
219 
220     for (auto ch : chints) {
221         canvas->save();
222         for (auto q : qualities) {
223             if (image->scalePixels(storage, q, ch)) {
224                 draw_pixmap(canvas, storage);
225             }
226             canvas->translate(70, 0);
227         }
228         canvas->restore();
229         canvas->translate(0, 45);
230     }
231 }
232 
draw_contents(SkCanvas * canvas)233 static void draw_contents(SkCanvas* canvas) {
234     SkPaint paint;
235     paint.setStyle(SkPaint::kStroke_Style);
236     paint.setStrokeWidth(20);
237     canvas->drawCircle(50, 50, 35, paint);
238 }
239 
make_raster(const SkImageInfo & info,GrContext *,void (* draw)(SkCanvas *))240 static sk_sp<SkImage> make_raster(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
241     auto surface(SkSurface::MakeRaster(info));
242     draw(surface->getCanvas());
243     return surface->makeImageSnapshot();
244 }
245 
make_picture(const SkImageInfo & info,GrContext *,void (* draw)(SkCanvas *))246 static sk_sp<SkImage> make_picture(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
247     SkPictureRecorder recorder;
248     draw(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
249     return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
250                                     info.dimensions(), nullptr, nullptr, SkImage::BitDepth::kU8,
251                                     SkColorSpace::MakeSRGB());
252 }
253 
make_codec(const SkImageInfo & info,GrContext *,void (* draw)(SkCanvas *))254 static sk_sp<SkImage> make_codec(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
255     sk_sp<SkImage> image(make_raster(info, nullptr, draw));
256     return SkImage::MakeFromEncoded(image->encodeToData());
257 }
258 
make_gpu(const SkImageInfo & info,GrContext * ctx,void (* draw)(SkCanvas *))259 static sk_sp<SkImage> make_gpu(const SkImageInfo& info, GrContext* ctx, void (*draw)(SkCanvas*)) {
260     if (!ctx) { return nullptr; }
261     auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info));
262     if (!surface) { return nullptr; }
263     draw(surface->getCanvas());
264     return surface->makeImageSnapshot();
265 }
266 
267 typedef sk_sp<SkImage> (*ImageMakerProc)(const SkImageInfo&, GrContext*, void (*)(SkCanvas*));
268 
269 class ScalePixelsGM : public skiagm::GM {
270 public:
ScalePixelsGM()271     ScalePixelsGM() {}
272 
273 protected:
onShortName()274     SkString onShortName() override {
275         return SkString("scale-pixels");
276     }
277 
onISize()278     SkISize onISize() override {
279         return SkISize::Make(960, 1200);
280     }
281 
onDraw(SkCanvas * canvas)282     void onDraw(SkCanvas* canvas) override {
283         const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
284 
285         const ImageMakerProc procs[] = {
286             make_codec, make_raster, make_picture, make_codec, make_gpu,
287         };
288         for (auto& proc : procs) {
289             sk_sp<SkImage> image(proc(info, canvas->getGrContext(), draw_contents));
290             if (image) {
291                 show_scaled_pixels(canvas, image.get());
292             }
293             canvas->translate(0, 120);
294         }
295     }
296 
297 private:
298     typedef skiagm::GM INHERITED;
299 };
300 DEF_GM( return new ScalePixelsGM; )
301 
302 ///////////////////////////////////////////////////////////////////////////////////////////////////
303 
304 DEF_SIMPLE_GM(new_texture_image, canvas, 280, 60) {
305     GrContext* context = canvas->getGrContext();
306     if (!context) {
307         skiagm::GM::DrawGpuOnlyMessage(canvas);
308         return;
309     }
310 
__anond5b0893e0202(SkCanvas* canvas) 311     auto render_image = [](SkCanvas* canvas) {
312         canvas->clear(SK_ColorBLUE);
313         SkPaint paint;
314         paint.setColor(SK_ColorRED);
315         canvas->drawRect(SkRect::MakeXYWH(10.f,10.f,10.f,10.f), paint);
316         paint.setColor(SK_ColorGREEN);
317         canvas->drawRect(SkRect::MakeXYWH(30.f,10.f,10.f,10.f), paint);
318         paint.setColor(SK_ColorYELLOW);
319         canvas->drawRect(SkRect::MakeXYWH(10.f,30.f,10.f,10.f), paint);
320         paint.setColor(SK_ColorCYAN);
321         canvas->drawRect(SkRect::MakeXYWH(30.f,30.f,10.f,10.f), paint);
322     };
323 
324     static constexpr int kSize = 50;
325     SkBitmap bmp;
326     bmp.allocPixels(SkImageInfo::MakeS32(kSize, kSize, kPremul_SkAlphaType));
327     SkCanvas bmpCanvas(bmp);
328     render_image(&bmpCanvas);
329 
330     std::function<sk_sp<SkImage>()> imageFactories[] = {
331         // Create sw raster image.
__anond5b0893e0302null332         [bmp] {
333             return SkImage::MakeFromBitmap(bmp);
334         },
335         // Create encoded image.
__anond5b0893e0402null336         [bmp] {
337             sk_sp<SkData> src(
338                 sk_tool_utils::EncodeImageToData(bmp, SkEncodedImageFormat::kPNG, 100));
339             return SkImage::MakeFromEncoded(std::move(src));
340         },
341         // Create YUV encoded image.
__anond5b0893e0502null342         [bmp] {
343             sk_sp<SkData> src(
344                 sk_tool_utils::EncodeImageToData(bmp, SkEncodedImageFormat::kJPEG, 100));
345             return SkImage::MakeFromEncoded(std::move(src));
346         },
347         // Create a picture image.
__anond5b0893e0602null348         [render_image] {
349             SkPictureRecorder recorder;
350             SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kSize), SkIntToScalar(kSize));
351             render_image(canvas);
352             sk_sp<SkColorSpace> srgbColorSpace = SkColorSpace::MakeSRGB();
353             return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
354                                             SkISize::Make(kSize, kSize), nullptr, nullptr,
355                                             SkImage::BitDepth::kU8, srgbColorSpace);
356         },
357         // Create a texture image
__anond5b0893e0702() 358         [context, render_image]() -> sk_sp<SkImage> {
359             auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kYes,
360                                                      SkImageInfo::MakeS32(kSize, kSize,
361                                                                           kPremul_SkAlphaType)));
362             if (!surface) {
363                 return nullptr;
364             }
365             render_image(surface->getCanvas());
366             return surface->makeImageSnapshot();
367         }
368     };
369 
370     constexpr SkScalar kPad = 5.f;
371     canvas->translate(kPad, kPad);
372     for (auto factory : imageFactories) {
373         auto image(factory());
374         if (image) {
375             sk_sp<SkImage> texImage(image->makeTextureImage(context,
376                                                             canvas->imageInfo().colorSpace()));
377             if (texImage) {
378                 canvas->drawImage(texImage, 0, 0);
379             }
380         }
381         canvas->translate(kSize + kPad, 0);
382     }
383 }
384