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 "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