1 /*
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 
8 #include "gm.h"
9 #include "sk_tool_utils.h"
10 
11 #include "SkPictureImageFilter.h"
12 #include "SkPictureRecorder.h"
13 
14 #include "SkImage.h"
15 #include "SkImageSource.h"
16 
17 // This GM exercises the SkPictureImageFilter ImageFilter class.
18 
19 static void fill_rect_filtered(SkCanvas* canvas,
20                                const SkRect& clipRect,
21                                sk_sp<SkImageFilter> filter) {
22     SkPaint paint;
23     paint.setImageFilter(filter);
24     canvas->save();
25     canvas->clipRect(clipRect);
26     canvas->drawPaint(paint);
27     canvas->restore();
28 }
29 
30 static sk_sp<SkPicture> make_picture() {
31     SkPictureRecorder recorder;
32     SkCanvas* canvas = recorder.beginRecording(100, 100, nullptr, 0);
33     SkPaint paint;
34     paint.setAntiAlias(true);
35     sk_tool_utils::set_portable_typeface(&paint);
36     paint.setColor(0xFFFFFFFF);
37     paint.setTextSize(SkIntToScalar(96));
38     const char* str = "e";
39     canvas->drawString(str, SkIntToScalar(20), SkIntToScalar(70), paint);
40     return recorder.finishRecordingAsPicture();
41 }
42 
43 // Create a picture that will draw LCD text
44 static sk_sp<SkPicture> make_LCD_picture() {
45     SkPictureRecorder recorder;
46     SkCanvas* canvas = recorder.beginRecording(100, 100, nullptr, 0);
47     canvas->clear(SK_ColorTRANSPARENT);
48     SkPaint paint;
49     paint.setLCDRenderText(true);   // want LCD
50     paint.setAntiAlias(true);       // need AA for LCD
51     sk_tool_utils::set_portable_typeface(&paint);
52     paint.setColor(0xFFFFFFFF);
53     // this has to be small enough that it doesn't become a path
54     paint.setTextSize(SkIntToScalar(36));
55     const char* str = "e";
56     canvas->drawString(str, SkIntToScalar(20), SkIntToScalar(70), paint);
57     return recorder.finishRecordingAsPicture();
58 }
59 
60 class PictureImageFilterGM : public skiagm::GM {
61 public:
62     PictureImageFilterGM() { }
63 
64 protected:
65     SkString onShortName() override {
66         return SkString("pictureimagefilter");
67     }
68 
69     SkISize onISize() override { return SkISize::Make(600, 300); }
70 
71     void onOnceBeforeDraw() override {
72         fPicture = make_picture();
73         fLCDPicture = make_LCD_picture();
74     }
75 
76     sk_sp<SkImageFilter> make(sk_sp<SkPicture> pic, SkRect r, SkFilterQuality fq) {
77         SkISize dim = { SkScalarRoundToInt(r.width()), SkScalarRoundToInt(r.height()) };
78         auto img = SkImage::MakeFromPicture(pic, dim, nullptr, nullptr,
79                                             SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
80         return SkImageSource::Make(img, r, r, fq);
81     }
82     sk_sp<SkImageFilter> make(SkFilterQuality fq) {
83         return make(fPicture, fPicture->cullRect(), fq);
84     }
85 
86     void onDraw(SkCanvas* canvas) override {
87         canvas->clear(SK_ColorGRAY);
88         {
89             SkRect srcRect = SkRect::MakeXYWH(20, 20, 30, 30);
90             SkRect emptyRect = SkRect::MakeXYWH(20, 20, 0, 0);
91             SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100);
92             sk_sp<SkImageFilter> pictureSource(SkPictureImageFilter::Make(fPicture));
93             sk_sp<SkImageFilter> pictureSourceSrcRect(SkPictureImageFilter::Make(fPicture,
94                                                                                  srcRect));
95             sk_sp<SkImageFilter> pictureSourceEmptyRect(SkPictureImageFilter::Make(fPicture,
96                                                                                    emptyRect));
97             sk_sp<SkImageFilter> pictureSourceResampled = make(kLow_SkFilterQuality);
98             sk_sp<SkImageFilter> pictureSourcePixelated = make(kNone_SkFilterQuality);
99 
100             canvas->save();
101             // Draw the picture unscaled.
102             fill_rect_filtered(canvas, bounds, pictureSource);
103             canvas->translate(SkIntToScalar(100), 0);
104 
105             // Draw an unscaled subset of the source picture.
106             fill_rect_filtered(canvas, bounds, pictureSourceSrcRect);
107             canvas->translate(SkIntToScalar(100), 0);
108 
109             // Draw the picture to an empty rect (should draw nothing).
110             fill_rect_filtered(canvas, bounds, pictureSourceEmptyRect);
111             canvas->translate(SkIntToScalar(100), 0);
112 
113             // Draw the LCD picture to a layer
114             {
115                 SkPaint stroke;
116                 stroke.setStyle(SkPaint::kStroke_Style);
117 
118                 canvas->drawRect(bounds, stroke);
119 
120                 SkPaint paint;
121                 paint.setImageFilter(make(fLCDPicture, fPicture->cullRect(), kNone_SkFilterQuality));
122 
123                 canvas->scale(4, 4);
124                 canvas->translate(-0.9f*srcRect.fLeft, -2.45f*srcRect.fTop);
125 
126                 canvas->saveLayerPreserveLCDTextRequests(&bounds, &paint);
127                 canvas->restore();
128             }
129 
130             canvas->restore();
131 
132             // Draw the picture scaled
133             canvas->translate(0, SkIntToScalar(100));
134             canvas->scale(200 / srcRect.width(), 200 / srcRect.height());
135             canvas->translate(-srcRect.fLeft, -srcRect.fTop);
136             fill_rect_filtered(canvas, srcRect, pictureSource);
137 
138             // Draw the picture scaled, but rasterized at original resolution
139             canvas->translate(srcRect.width(), 0);
140             fill_rect_filtered(canvas, srcRect, pictureSourceResampled);
141 
142             // Draw the picture scaled, pixelated
143             canvas->translate(srcRect.width(), 0);
144             fill_rect_filtered(canvas, srcRect, pictureSourcePixelated);
145         }
146     }
147 
148 private:
149     sk_sp<SkPicture> fPicture;
150     sk_sp<SkPicture> fLCDPicture;
151 
152     typedef GM INHERITED;
153 };
154 
155 ///////////////////////////////////////////////////////////////////////////////
156 
157 DEF_GM( return new PictureImageFilterGM; )
158