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