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