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