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 "SkPath.h"
16#include "SkRandom.h"
17#include "SkRegion.h"
18#include "SkShader.h"
19#include "SkUtils.h"
20#include "SkColorPriv.h"
21#include "SkColorFilter.h"
22#include "SkTime.h"
23#include "SkTypeface.h"
24
25#include "SkStream.h"
26#include "SkColorPriv.h"
27#include "SkBlurMaskFilter.h"
28
29static void setNamedTypeface(SkPaint* paint, const char name[]) {
30    paint->setTypeface(SkTypeface::MakeFromName(name, SkFontStyle()));
31}
32
33static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
34
35class XfermodesBlurView : public SampleView {
36    SkBitmap    fBG;
37    SkBitmap    fSrcB, fDstB;
38
39    void draw_mode(SkCanvas* canvas, SkBlendMode mode, int alpha, SkScalar x, SkScalar y) {
40        SkPaint p;
41        p.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
42                                               SkBlurMask::ConvertRadiusToSigma(5),
43                                               SkBlurMaskFilter::kNone_BlurFlag));
44
45        SkScalar ww = SkIntToScalar(W);
46        SkScalar hh = SkIntToScalar(H);
47
48        // draw a circle covering the upper
49        // left three quarters of the canvas
50        p.setColor(0xFFCC44FF);
51        SkRect r;
52        r.set(0, 0, ww*3/4, hh*3/4);
53        r.offset(x, y);
54        canvas->drawOval(r, p);
55
56        p.setBlendMode(mode);
57
58        // draw a square overlapping the circle
59        // in the lower right of the canvas
60        p.setColor(0x00AA6633 | alpha << 24);
61        r.set(ww/3, hh/3, ww*19/20, hh*19/20);
62        r.offset(x, y);
63        canvas->drawRect(r, p);
64    }
65
66public:
67    const static int W = 64;
68    const static int H = 64;
69    XfermodesBlurView() {
70        fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType, kPremul_SkAlphaType),
71                          gBG, 4);
72    }
73
74protected:
75    // overrides from SkEventSink
76    virtual bool onQuery(SkEvent* evt) {
77        if (SampleCode::TitleQ(*evt)) {
78            SampleCode::TitleR(evt, "XfermodesBlur");
79            return true;
80        }
81        return this->INHERITED::onQuery(evt);
82    }
83
84    virtual void onDrawContent(SkCanvas* canvas) {
85        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
86
87        if (false) {
88            SkPaint paint;
89            paint.setAntiAlias(true);
90            paint.setTextSize(50);
91            paint.setTypeface(SkTypeface::MakeFromName("Arial Unicode MS", SkFontStyle()));
92            char buffer[10];
93            size_t len = SkUTF8_FromUnichar(0x8500, buffer);
94            canvas->drawText(buffer, len, 40, 40, paint);
95            return;
96        }
97        if (false) {
98            SkPaint paint;
99            paint.setAntiAlias(true);
100
101            SkRect r0 = { 0, 0, 10.5f, 20 };
102            SkRect r1 = { 10.5f, 10, 20, 30 };
103            paint.setColor(SK_ColorRED);
104            canvas->drawRect(r0, paint);
105            paint.setColor(SK_ColorBLUE);
106            canvas->drawRect(r1, paint);
107            return;
108        }
109
110        const SkBlendMode gModes[] = {
111            SkBlendMode::kClear,
112            SkBlendMode::kSrc,
113            SkBlendMode::kDst,
114            SkBlendMode::kSrcOver,
115            SkBlendMode::kDstOver,
116            SkBlendMode::kSrcIn,
117            SkBlendMode::kDstIn,
118            SkBlendMode::kSrcOut,
119            SkBlendMode::kDstOut,
120            SkBlendMode::kSrcATop,
121            SkBlendMode::kDstATop,
122            SkBlendMode::kXor,
123            SkBlendMode::kPlus,
124        };
125
126        const SkScalar w = SkIntToScalar(W);
127        const SkScalar h = SkIntToScalar(H);
128        SkMatrix m;
129        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
130        auto s = SkShader::MakeBitmapShader(fBG, SkShader::kRepeat_TileMode,
131                                            SkShader::kRepeat_TileMode, &m);
132
133        SkPaint labelP;
134        labelP.setAntiAlias(true);
135        labelP.setLCDRenderText(true);
136        labelP.setTextAlign(SkPaint::kCenter_Align);
137        setNamedTypeface(&labelP, "Menlo Regular");
138
139        const int W = 5;
140
141        SkScalar x0 = 0;
142        for (int twice = 0; twice < 2; twice++) {
143            SkScalar x = x0, y = 0;
144            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
145                SkRect r;
146                r.set(x, y, x+w, y+h);
147
148                SkPaint p;
149                p.setStyle(SkPaint::kFill_Style);
150                p.setShader(s);
151                canvas->drawRect(r, p);
152
153                canvas->saveLayer(&r, nullptr);
154                draw_mode(canvas, gModes[i], twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
155                canvas->restore();
156
157                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
158                p.setStyle(SkPaint::kStroke_Style);
159                p.setShader(nullptr);
160                canvas->drawRect(r, p);
161
162                const char* label = SkBlendMode_Name(gModes[i]);
163                canvas->drawString(label,
164                                 x + w/2, y - labelP.getTextSize()/2, labelP);
165                x += w + SkIntToScalar(10);
166                if ((i % W) == W - 1) {
167                    x = x0;
168                    y += h + SkIntToScalar(30);
169                }
170            }
171            x0 += SkIntToScalar(400);
172        }
173    }
174
175private:
176    typedef SampleView INHERITED;
177};
178
179//////////////////////////////////////////////////////////////////////////////
180
181static SkView* MyFactory() { return new XfermodesBlurView; }
182static SkViewRegister reg(MyFactory);
183