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