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