1/*
2 * Copyright 2011 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 "SampleCode.h"
9#include "SkView.h"
10#include "SkBlurMask.h"
11#include "SkCanvas.h"
12#include "SkCornerPathEffect.h"
13#include "SkGradientShader.h"
14#include "SkGraphics.h"
15#include "SkImageDecoder.h"
16#include "SkPath.h"
17#include "SkRandom.h"
18#include "SkRegion.h"
19#include "SkShader.h"
20#include "SkUtils.h"
21#include "SkColorPriv.h"
22#include "SkColorFilter.h"
23#include "SkTime.h"
24#include "SkTypeface.h"
25#include "SkXfermode.h"
26
27#include "SkStream.h"
28#include "SkXMLParser.h"
29#include "SkColorPriv.h"
30#include "SkImageDecoder.h"
31#include "SkBlurMaskFilter.h"
32
33static void setNamedTypeface(SkPaint* paint, const char name[]) {
34    SkTypeface* face = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
35    paint->setTypeface(face);
36    SkSafeUnref(face);
37}
38
39static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
40
41class XfermodesBlurView : public SampleView {
42    SkBitmap    fBG;
43    SkBitmap    fSrcB, fDstB;
44
45    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
46                   SkScalar x, SkScalar y) {
47        SkPaint p;
48        SkMaskFilter* mf = SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
49                                       SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)),
50                                       SkBlurMaskFilter::kNone_BlurFlag);
51        p.setMaskFilter(mf)->unref();
52
53        SkScalar ww = SkIntToScalar(W);
54        SkScalar hh = SkIntToScalar(H);
55
56        // draw a circle covering the upper
57        // left three quarters of the canvas
58        p.setColor(0xFFCC44FF);
59        SkRect r;
60        r.set(0, 0, ww*3/4, hh*3/4);
61        r.offset(x, y);
62        canvas->drawOval(r, p);
63
64        p.setXfermode(mode);
65
66        // draw a square overlapping the circle
67        // in the lower right of the canvas
68        p.setColor(0x00AA6633 | alpha << 24);
69        r.set(ww/3, hh/3, ww*19/20, hh*19/20);
70        r.offset(x, y);
71        canvas->drawRect(r, p);
72    }
73
74public:
75    const static int W = 64;
76    const static int H = 64;
77    XfermodesBlurView() {
78        fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType, kPremul_SkAlphaType),
79                          gBG, 4);
80    }
81
82protected:
83    // overrides from SkEventSink
84    virtual bool onQuery(SkEvent* evt) {
85        if (SampleCode::TitleQ(*evt)) {
86            SampleCode::TitleR(evt, "XfermodesBlur");
87            return true;
88        }
89        return this->INHERITED::onQuery(evt);
90    }
91
92    virtual void onDrawContent(SkCanvas* canvas) {
93        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
94
95        if (false) {
96            SkPaint paint;
97            paint.setAntiAlias(true);
98            paint.setTextSize(50);
99            paint.setTypeface(SkTypeface::CreateFromName("Arial Unicode MS", SkTypeface::kNormal));
100            SkSafeUnref(paint.getTypeface());
101            char buffer[10];
102            size_t len = SkUTF8_FromUnichar(0x8500, buffer);
103            canvas->drawText(buffer, len, 40, 40, paint);
104            return;
105        }
106        if (false) {
107            SkPaint paint;
108            paint.setAntiAlias(true);
109
110            SkRect r0 = { 0, 0, 10.5f, 20 };
111            SkRect r1 = { 10.5f, 10, 20, 30 };
112            paint.setColor(SK_ColorRED);
113            canvas->drawRect(r0, paint);
114            paint.setColor(SK_ColorBLUE);
115            canvas->drawRect(r1, paint);
116            return;
117        }
118
119        const struct {
120            SkXfermode::Mode  fMode;
121            const char*         fLabel;
122        } gModes[] = {
123            { SkXfermode::kClear_Mode,    "Clear"     },
124            { SkXfermode::kSrc_Mode,      "Src"       },
125            { SkXfermode::kDst_Mode,      "Dst"       },
126            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
127            { SkXfermode::kDstOver_Mode,  "DstOver"   },
128            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
129            { SkXfermode::kDstIn_Mode,    "DstIn"     },
130            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
131            { SkXfermode::kDstOut_Mode,   "DstOut"    },
132            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
133            { SkXfermode::kDstATop_Mode,  "DstATop"   },
134            { SkXfermode::kXor_Mode,      "Xor"       },
135
136            { SkXfermode::kPlus_Mode,         "Plus"          },
137            /*{ SkXfermode::kModulate_Mode,     "Modulate"      },
138            { SkXfermode::kScreen_Mode,       "Screen"        },
139            { SkXfermode::kOverlay_Mode,      "Overlay"       },
140            { SkXfermode::kDarken_Mode,       "Darken"        },
141            { SkXfermode::kLighten_Mode,      "Lighten"       },
142            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
143            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
144            { SkXfermode::kHardLight_Mode,    "HardLight"     },
145            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
146            { SkXfermode::kDifference_Mode,   "Difference"    },
147            { SkXfermode::kExclusion_Mode,    "Exclusion"     },*/
148        };
149
150        const SkScalar w = SkIntToScalar(W);
151        const SkScalar h = SkIntToScalar(H);
152        SkMatrix m;
153        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
154        SkShader* s = SkShader::CreateBitmapShader(fBG,
155                                                   SkShader::kRepeat_TileMode,
156                                                   SkShader::kRepeat_TileMode,
157                                                   &m);
158
159        SkPaint labelP;
160        labelP.setAntiAlias(true);
161        labelP.setLCDRenderText(true);
162        labelP.setTextAlign(SkPaint::kCenter_Align);
163        setNamedTypeface(&labelP, "Menlo Regular");
164
165        const int W = 5;
166
167        SkScalar x0 = 0;
168        for (int twice = 0; twice < 2; twice++) {
169            SkScalar x = x0, y = 0;
170            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
171                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
172                SkAutoUnref aur(mode);
173                SkRect r;
174                r.set(x, y, x+w, y+h);
175
176                SkPaint p;
177                p.setStyle(SkPaint::kFill_Style);
178                p.setShader(s);
179                canvas->drawRect(r, p);
180
181                canvas->saveLayer(&r, NULL);
182                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
183                canvas->restore();
184
185                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
186                p.setStyle(SkPaint::kStroke_Style);
187                p.setShader(NULL);
188                canvas->drawRect(r, p);
189
190                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
191                                 x + w/2, y - labelP.getTextSize()/2, labelP);
192                x += w + SkIntToScalar(10);
193                if ((i % W) == W - 1) {
194                    x = x0;
195                    y += h + SkIntToScalar(30);
196                }
197            }
198            x0 += SkIntToScalar(400);
199        }
200        s->unref();
201    }
202
203private:
204    typedef SampleView INHERITED;
205};
206
207//////////////////////////////////////////////////////////////////////////////
208
209static SkView* MyFactory() { return new XfermodesBlurView; }
210static SkViewRegister reg(MyFactory);
211