1 /* 2 * Copyright 2012 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 10 #include "SkArithmeticMode.h" 11 #include "SkDevice.h" 12 #include "SkBitmapSource.h" 13 #include "SkBlurImageFilter.h" 14 #include "SkColorFilter.h" 15 #include "SkColorFilterImageFilter.h" 16 #include "SkColorMatrixFilter.h" 17 #include "SkReadBuffer.h" 18 #include "SkWriteBuffer.h" 19 #include "SkMergeImageFilter.h" 20 #include "SkMorphologyImageFilter.h" 21 #include "SkTestImageFilters.h" 22 #include "SkXfermodeImageFilter.h" 23 24 // More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't 25 // perform a draw and this one does. 26 class SimpleOffsetFilter : public SkImageFilter { 27 public: 28 static SkImageFilter* Create(SkScalar dx, SkScalar dy, SkImageFilter* input) { 29 return SkNEW_ARGS(SimpleOffsetFilter, (dx, dy, input)); 30 } 31 32 virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const Context& ctx, 33 SkBitmap* dst, SkIPoint* offset) const SK_OVERRIDE { 34 SkBitmap source = src; 35 SkImageFilter* input = getInput(0); 36 SkIPoint srcOffset = SkIPoint::Make(0, 0); 37 if (NULL != input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) { 38 return false; 39 } 40 41 SkIRect bounds; 42 if (!this->applyCropRect(ctx, proxy, source, &srcOffset, &bounds, &source)) { 43 return false; 44 } 45 46 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); 47 SkCanvas canvas(device); 48 SkPaint paint; 49 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 50 canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint); 51 *dst = device->accessBitmap(false); 52 offset->fX += bounds.left(); 53 offset->fY += bounds.top(); 54 return true; 55 } 56 57 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter); 58 59 protected: 60 explicit SimpleOffsetFilter(SkReadBuffer& buffer) 61 : SkImageFilter(1, buffer) { 62 fDX = buffer.readScalar(); 63 fDY = buffer.readScalar(); 64 } 65 66 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE { 67 this->SkImageFilter::flatten(buffer); 68 buffer.writeScalar(fDX); 69 buffer.writeScalar(fDY); 70 } 71 72 private: 73 SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input) 74 : SkImageFilter(input), fDX(dx), fDY(dy) {} 75 76 SkScalar fDX, fDY; 77 }; 78 79 SkFlattenable::Registrar registrar("SimpleOffsetFilter", 80 SimpleOffsetFilter::CreateProc, 81 SimpleOffsetFilter::GetFlattenableType()); 82 83 class ImageFiltersGraphGM : public skiagm::GM { 84 public: 85 ImageFiltersGraphGM() {} 86 87 protected: 88 virtual uint32_t onGetFlags() const SK_OVERRIDE { 89 return kSkipTiled_Flag; 90 } 91 92 virtual SkString onShortName() { 93 return SkString("imagefiltersgraph"); 94 } 95 96 void make_bitmap() { 97 fBitmap.allocN32Pixels(100, 100); 98 SkCanvas canvas(fBitmap); 99 canvas.clear(0x00000000); 100 SkPaint paint; 101 paint.setAntiAlias(true); 102 paint.setColor(0xFFFFFFFF); 103 paint.setTextSize(SkIntToScalar(96)); 104 const char* str = "e"; 105 canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint); 106 } 107 108 void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint) { 109 canvas->save(); 110 canvas->clipRect(SkRect::MakeXYWH(0, 0, 111 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()))); 112 canvas->drawBitmap(bitmap, 0, 0, &paint); 113 canvas->restore(); 114 } 115 116 virtual SkISize onISize() { return SkISize::Make(500, 150); } 117 118 virtual void onOnceBeforeDraw() { 119 this->make_bitmap(); 120 } 121 122 virtual void onDraw(SkCanvas* canvas) { 123 canvas->clear(0x00000000); 124 { 125 SkAutoTUnref<SkImageFilter> bitmapSource(SkBitmapSource::Create(fBitmap)); 126 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, 127 SkXfermode::kSrcIn_Mode)); 128 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(4.0f, 4.0f, bitmapSource)); 129 SkAutoTUnref<SkImageFilter> erode(SkErodeImageFilter::Create(4, 4, blur)); 130 SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode)); 131 SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(blur, color)); 132 133 SkPaint paint; 134 paint.setImageFilter(merge); 135 canvas->drawPaint(paint); 136 canvas->translate(SkIntToScalar(100), 0); 137 } 138 { 139 SkAutoTUnref<SkImageFilter> morph(SkDilateImageFilter::Create(5, 5)); 140 141 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0, 142 0, SK_Scalar1, 0, 0, 0, 143 0, 0, SK_Scalar1, 0, 0, 144 0, 0, 0, 0.5f, 0 }; 145 146 SkAutoTUnref<SkColorFilter> matrixFilter(SkColorMatrixFilter::Create(matrix)); 147 SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph)); 148 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); 149 SkAutoTUnref<SkImageFilter> blendColor(SkXfermodeImageFilter::Create(mode, colorMorph)); 150 151 SkPaint paint; 152 paint.setImageFilter(blendColor); 153 drawClippedBitmap(canvas, fBitmap, paint); 154 canvas->translate(SkIntToScalar(100), 0); 155 } 156 { 157 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0, 158 0, SK_Scalar1, 0, 0, 0, 159 0, 0, SK_Scalar1, 0, 0, 160 0, 0, 0, 0.5f, 0 }; 161 SkAutoTUnref<SkColorMatrixFilter> matrixCF(SkColorMatrixFilter::Create(matrix)); 162 SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(matrixCF)); 163 SkAutoTUnref<SkImageFilter> offsetFilter( 164 SimpleOffsetFilter::Create(10.0f, 10.f, matrixFilter)); 165 166 SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0)); 167 SkAutoTUnref<SkXfermodeImageFilter> arithFilter( 168 SkXfermodeImageFilter::Create(arith, matrixFilter, offsetFilter)); 169 170 SkPaint paint; 171 paint.setImageFilter(arithFilter); 172 drawClippedBitmap(canvas, fBitmap, paint); 173 canvas->translate(SkIntToScalar(100), 0); 174 } 175 { 176 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create( 177 SkIntToScalar(10), SkIntToScalar(10))); 178 179 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode)); 180 SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100))); 181 SkAutoTUnref<SkImageFilter> blend( 182 SkXfermodeImageFilter::Create(mode, blur, NULL, &cropRect)); 183 184 SkPaint paint; 185 paint.setImageFilter(blend); 186 drawClippedBitmap(canvas, fBitmap, paint); 187 canvas->translate(SkIntToScalar(100), 0); 188 } 189 { 190 // Test that crop offsets are absolute, not relative to the parent's crop rect. 191 SkAutoTUnref<SkColorFilter> cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE, 192 SkXfermode::kSrcIn_Mode)); 193 SkAutoTUnref<SkColorFilter> cf2(SkColorFilter::CreateModeFilter(SK_ColorGREEN, 194 SkXfermode::kSrcIn_Mode)); 195 SkImageFilter::CropRect outerRect(SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(10), 196 SkIntToScalar(80), SkIntToScalar(80))); 197 SkImageFilter::CropRect innerRect(SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20), 198 SkIntToScalar(60), SkIntToScalar(60))); 199 SkAutoTUnref<SkImageFilter> color1(SkColorFilterImageFilter::Create(cf1, NULL, &outerRect)); 200 SkAutoTUnref<SkImageFilter> color2(SkColorFilterImageFilter::Create(cf2, color1, &innerRect)); 201 202 SkPaint paint; 203 paint.setImageFilter(color2); 204 paint.setColor(0xFFFF0000); 205 canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint); 206 canvas->translate(SkIntToScalar(100), 0); 207 } 208 } 209 210 private: 211 typedef GM INHERITED; 212 SkBitmap fBitmap; 213 }; 214 215 /////////////////////////////////////////////////////////////////////////////// 216 217 static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; } 218 static skiagm::GMRegistry reg(MyFactory); 219