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 "SkImage.h" 9 #include "SkImageSource.h" 10 #include "SkOffsetImageFilter.h" 11 #include "SkSurface.h" 12 #include "gm.h" 13 #include "sk_tool_utils.h" 14 15 #define WIDTH 600 16 #define HEIGHT 100 17 #define MARGIN 12 18 19 class OffsetImageFilterGM : public skiagm::GM { 20 public: 21 OffsetImageFilterGM() { 22 this->setBGColor(0xFF000000); 23 } 24 25 protected: 26 SkString onShortName() override { 27 return SkString("offsetimagefilter"); 28 } 29 30 SkISize onISize() override { 31 return SkISize::Make(WIDTH, HEIGHT); 32 } 33 34 void onOnceBeforeDraw() override { 35 fBitmap = SkImage::MakeFromBitmap( 36 sk_tool_utils::create_string_bitmap(80, 80, 0xD000D000, 15, 65, 96, "e")); 37 38 fCheckerboard = SkImage::MakeFromBitmap( 39 sk_tool_utils::create_checkerboard_bitmap(80, 80, 40 0xFFA0A0A0, 41 0xFF404040, 42 8)); 43 } 44 45 void onDraw(SkCanvas* canvas) override { 46 canvas->clear(SK_ColorBLACK); 47 SkPaint paint; 48 49 for (int i = 0; i < 4; i++) { 50 sk_sp<SkImage> image = (i & 0x01) ? fCheckerboard : fBitmap; 51 SkIRect cropRect = SkIRect::MakeXYWH(i * 12, 52 i * 8, 53 image->width() - i * 8, 54 image->height() - i * 12); 55 SkImageFilter::CropRect rect(SkRect::Make(cropRect)); 56 sk_sp<SkImageFilter> tileInput(SkImageSource::Make(image)); 57 SkScalar dx = SkIntToScalar(i*5); 58 SkScalar dy = SkIntToScalar(i*10); 59 paint.setImageFilter(SkOffsetImageFilter::Make(dx, dy, std::move(tileInput), &rect)); 60 DrawClippedImage(canvas, image.get(), paint, 1, cropRect); 61 canvas->translate(SkIntToScalar(image->width() + MARGIN), 0); 62 } 63 64 SkIRect cropRect = SkIRect::MakeXYWH(0, 0, 100, 100); 65 SkImageFilter::CropRect rect(SkRect::Make(cropRect)); 66 paint.setImageFilter(SkOffsetImageFilter::Make(-5, -10, nullptr, &rect)); 67 DrawClippedImage(canvas, fBitmap.get(), paint, 2, cropRect); 68 } 69 private: 70 static void DrawClippedImage(SkCanvas* canvas, const SkImage* image, const SkPaint& paint, 71 SkScalar scale, const SkIRect& cropRect) { 72 SkRect clipRect = SkRect::MakeIWH(image->width(), image->height()); 73 74 canvas->save(); 75 canvas->clipRect(clipRect); 76 canvas->scale(scale, scale); 77 canvas->drawImage(image, 0, 0, &paint); 78 canvas->restore(); 79 80 // Draw a boundary rect around the intersection of the clip rect and crop rect. 81 SkRect cropRectFloat; 82 SkMatrix::MakeScale(scale, scale).mapRect(&cropRectFloat, SkRect::Make(cropRect)); 83 if (clipRect.intersect(cropRectFloat)) { 84 SkPaint strokePaint; 85 strokePaint.setStyle(SkPaint::kStroke_Style); 86 strokePaint.setStrokeWidth(2); 87 strokePaint.setColor(SK_ColorRED); 88 canvas->drawRect(clipRect, strokePaint); 89 } 90 } 91 92 sk_sp<SkImage> fBitmap, fCheckerboard; 93 94 typedef skiagm::GM INHERITED; 95 }; 96 DEF_GM( return new OffsetImageFilterGM; ) 97 98 ////////////////////////////////////////////////////////////////////////////// 99 100 class SimpleOffsetImageFilterGM : public skiagm::GM { 101 public: 102 SimpleOffsetImageFilterGM() {} 103 104 protected: 105 SkString onShortName() override { 106 return SkString("simple-offsetimagefilter"); 107 } 108 109 SkISize onISize() override { return SkISize::Make(640, 200); } 110 111 void doDraw(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imgf, 112 const SkRect* clipR = nullptr) { 113 SkPaint p; 114 115 if (clipR) { 116 p.setColor(0xFF00FF00); 117 p.setStyle(SkPaint::kStroke_Style); 118 canvas->drawRect(clipR->makeInset(SK_ScalarHalf, SK_ScalarHalf), p); 119 p.setStyle(SkPaint::kFill_Style); 120 } 121 122 if (imgf && imgf->cropRectIsSet()) { 123 SkImageFilter::CropRect cr = imgf->getCropRect(); 124 125 p.setColor(0x66FF00FF); 126 p.setStyle(SkPaint::kStroke_Style); 127 canvas->drawRect(cr.rect().makeInset(SK_ScalarHalf, SK_ScalarHalf), p); 128 p.setStyle(SkPaint::kFill_Style); 129 } 130 131 p.setColor(0x660000FF); 132 canvas->drawRect(r, p); 133 134 if (clipR) { 135 canvas->save(); 136 canvas->clipRect(*clipR); 137 } 138 if (imgf) { 139 p.setImageFilter(std::move(imgf)); 140 } 141 p.setColor(0x66FF0000); 142 canvas->drawRect(r, p); 143 144 if (clipR) { 145 canvas->restore(); 146 } 147 } 148 149 void onDraw(SkCanvas* canvas) override { 150 const SkRect r = SkRect::MakeWH(40, 40); 151 SkImageFilter::CropRect cr0(r); 152 SkImageFilter::CropRect cr1(SkRect::MakeWH(20, 20)); 153 const SkRect r2 = SkRect::MakeXYWH(40, 0, 40, 40); 154 SkImageFilter::CropRect cr2(r2); 155 156 canvas->translate(40, 40); 157 158 canvas->save(); 159 this->doDraw(canvas, r, nullptr); 160 161 canvas->translate(100, 0); 162 this->doDraw(canvas, r, SkOffsetImageFilter::Make(20, 20, nullptr)); 163 164 canvas->translate(100, 0); 165 this->doDraw(canvas, r, SkOffsetImageFilter::Make(20, 20, nullptr, &cr0)); 166 167 canvas->translate(100, 0); 168 this->doDraw(canvas, r, SkOffsetImageFilter::Make(20, 20, nullptr), &r); 169 170 canvas->translate(100, 0); 171 this->doDraw(canvas, r, SkOffsetImageFilter::Make(20, 20, nullptr, &cr1)); 172 173 SkRect clipR = SkRect::MakeXYWH(40, 40, 40, 40); 174 canvas->translate(100, 0); 175 this->doDraw(canvas, r, SkOffsetImageFilter::Make(20, 20, nullptr, nullptr), &clipR); 176 canvas->restore(); 177 178 // 2nd row 179 canvas->translate(0, 80); 180 181 /* 182 * combos of clip and crop rects that align with src and dst 183 */ 184 185 // crop==clip==src 186 this->doDraw(canvas, r, SkOffsetImageFilter::Make(40, 0, nullptr, &cr0), &r); 187 188 // crop==src, clip==dst 189 canvas->translate(100, 0); 190 this->doDraw(canvas, r, SkOffsetImageFilter::Make(40, 0, nullptr, &cr0), &r2); 191 192 // crop==dst, clip==src 193 canvas->translate(100, 0); 194 this->doDraw(canvas, r, SkOffsetImageFilter::Make(40, 0, nullptr, &cr2), &r); 195 196 // crop==clip==dst 197 canvas->translate(100, 0); 198 this->doDraw(canvas, r, SkOffsetImageFilter::Make(40, 0, nullptr, &cr2), &r2); 199 } 200 201 private: 202 typedef skiagm::GM INHERITED; 203 }; 204 DEF_GM( return new SimpleOffsetImageFilterGM; ) 205