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