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