Home | History | Annotate | Download | only in gm
      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.
     25 class SimpleOffsetFilter : public SkImageFilter {
     26 public:
     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 
     59 protected:
     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 
     72 private:
     73     SkScalar fDX, fDY;
     74 };
     75 
     76 static void init_flattenable(int*) {
     77     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SimpleOffsetFilter)
     78 }
     79 
     80 class ImageFiltersGraphGM : public skiagm::GM {
     81 public:
     82     ImageFiltersGraphGM() : fInitialized(false) {
     83         int dummy;
     84         SK_DECLARE_STATIC_ONCE(once);
     85         SkOnce(&once, init_flattenable, &dummy);
     86     }
     87 
     88 protected:
     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 
    187 private:
    188     typedef GM INHERITED;
    189     SkBitmap fBitmap;
    190     bool fInitialized;
    191 };
    192 
    193 ///////////////////////////////////////////////////////////////////////////////
    194 
    195 static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; }
    196 static skiagm::GMRegistry reg(MyFactory);
    197