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 "SkBitmapSource.h" 12#include "SkBlurImageFilter.h" 13#include "SkColorFilter.h" 14#include "SkColorFilterImageFilter.h" 15#include "SkColorMatrixFilter.h" 16#include "SkFlattenableBuffers.h" 17#include "SkMergeImageFilter.h" 18#include "SkMorphologyImageFilter.h" 19#include "SkOnce.h" 20#include "SkTestImageFilters.h" 21#include "SkXfermodeImageFilter.h" 22 23// More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't 24// perform a draw and this one does. 25class SimpleOffsetFilter : public SkImageFilter { 26public: 27 SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input) 28 : SkImageFilter(input), fDX(dx), fDY(dy) {} 29 30 virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, 31 SkBitmap* dst, SkIPoint* offset) SK_OVERRIDE { 32 SkBitmap source = src; 33 SkImageFilter* input = getInput(0); 34 SkIPoint srcOffset = SkIPoint::Make(0, 0); 35 if (NULL != input && !input->filterImage(proxy, src, ctm, &source, &srcOffset)) { 36 return false; 37 } 38 39 SkIRect bounds; 40 source.getBounds(&bounds); 41 42 if (!this->applyCropRect(&bounds, ctm)) { 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 59protected: 60 explicit SimpleOffsetFilter(SkFlattenableReadBuffer& buffer) 61 : SkImageFilter(1, buffer) { 62 fDX = buffer.readScalar(); 63 fDY = buffer.readScalar(); 64 } 65 66 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { 67 this->SkImageFilter::flatten(buffer); 68 buffer.writeScalar(fDX); 69 buffer.writeScalar(fDY); 70 } 71 72private: 73 SkScalar fDX, fDY; 74}; 75 76static void init_flattenable(int*) { 77 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SimpleOffsetFilter) 78} 79 80class ImageFiltersGraphGM : public skiagm::GM { 81public: 82 ImageFiltersGraphGM() : fInitialized(false) { 83 int dummy; 84 SK_DECLARE_STATIC_ONCE(once); 85 SkOnce(&once, init_flattenable, &dummy); 86 } 87 88protected: 89 virtual SkString onShortName() { 90 return SkString("imagefiltersgraph"); 91 } 92 93 void make_bitmap() { 94 fBitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); 95 fBitmap.allocPixels(); 96 SkBitmapDevice device(fBitmap); 97 SkCanvas canvas(&device); 98 canvas.clear(0x00000000); 99 SkPaint paint; 100 paint.setAntiAlias(true); 101 paint.setColor(0xFFFFFFFF); 102 paint.setTextSize(SkIntToScalar(96)); 103 const char* str = "e"; 104 canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint); 105 } 106 107 void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint) { 108 canvas->save(); 109 canvas->clipRect(SkRect::MakeXYWH(0, 0, 110 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()))); 111 canvas->drawBitmap(bitmap, 0, 0, &paint); 112 canvas->restore(); 113 } 114 115 virtual SkISize onISize() { return SkISize::Make(500, 150); } 116 117 virtual void onDraw(SkCanvas* canvas) { 118 if (!fInitialized) { 119 this->make_bitmap(); 120 fInitialized = true; 121 } 122 canvas->clear(0x00000000); 123 { 124 SkAutoTUnref<SkImageFilter> bitmapSource(new SkBitmapSource(fBitmap)); 125 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, 126 SkXfermode::kSrcIn_Mode)); 127 SkAutoTUnref<SkImageFilter> blur(new SkBlurImageFilter(4.0f, 4.0f, bitmapSource)); 128 SkAutoTUnref<SkImageFilter> erode(new SkErodeImageFilter(4, 4, blur)); 129 SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode)); 130 SkAutoTUnref<SkImageFilter> merge(new SkMergeImageFilter(blur, color)); 131 132 SkPaint paint; 133 paint.setImageFilter(merge); 134 canvas->drawPaint(paint); 135 canvas->translate(SkIntToScalar(100), 0); 136 } 137 { 138 SkAutoTUnref<SkImageFilter> morph(new SkDilateImageFilter(5, 5)); 139 140 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0, 141 0, SK_Scalar1, 0, 0, 0, 142 0, 0, SK_Scalar1, 0, 0, 143 0, 0, 0, 0.5f, 0 }; 144 145 SkAutoTUnref<SkColorFilter> matrixFilter(new SkColorMatrixFilter(matrix)); 146 SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph)); 147 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); 148 SkAutoTUnref<SkImageFilter> blendColor(new SkXfermodeImageFilter(mode, colorMorph)); 149 150 SkPaint paint; 151 paint.setImageFilter(blendColor); 152 drawClippedBitmap(canvas, fBitmap, paint); 153 canvas->translate(SkIntToScalar(100), 0); 154 } 155 { 156 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0, 157 0, SK_Scalar1, 0, 0, 0, 158 0, 0, SK_Scalar1, 0, 0, 159 0, 0, 0, 0.5f, 0 }; 160 SkColorMatrixFilter matrixCF(matrix); 161 SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(&matrixCF)); 162 SimpleOffsetFilter offsetFilter(SkIntToScalar(10), SkIntToScalar(10), matrixFilter); 163 164 SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0)); 165 SkXfermodeImageFilter arithFilter(arith, matrixFilter, &offsetFilter); 166 167 SkPaint paint; 168 paint.setImageFilter(&arithFilter); 169 drawClippedBitmap(canvas, fBitmap, paint); 170 canvas->translate(SkIntToScalar(100), 0); 171 } 172 { 173 SkAutoTUnref<SkImageFilter> blur(new SkBlurImageFilter( 174 SkIntToScalar(10), SkIntToScalar(10))); 175 176 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode)); 177 SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100))); 178 SkAutoTUnref<SkImageFilter> blend(new SkXfermodeImageFilter(mode, blur, NULL, &cropRect)); 179 180 SkPaint paint; 181 paint.setImageFilter(blend); 182 drawClippedBitmap(canvas, fBitmap, paint); 183 canvas->translate(SkIntToScalar(100), 0); 184 } 185 } 186 187private: 188 typedef GM INHERITED; 189 SkBitmap fBitmap; 190 bool fInitialized; 191}; 192 193/////////////////////////////////////////////////////////////////////////////// 194 195static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; } 196static skiagm::GMRegistry reg(MyFactory); 197