1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SampleCode.h"
9 #include "SkView.h"
10 #include "SkCanvas.h"
11 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h"
13 #include "SkGradientShader.h"
14 #include "SkPath.h"
15 #include "SkRegion.h"
16 #include "SkShader.h"
17 #include "SkUtils.h"
18 #include "SkColorPriv.h"
19 #include "SkColorFilter.h"
20 #include "SkStrokeRec.h"
21 #include "SkTypeface.h"
22 
rgb2gray(SkPMColor c)23 static inline SkPMColor rgb2gray(SkPMColor c) {
24     unsigned r = SkGetPackedR32(c);
25     unsigned g = SkGetPackedG32(c);
26     unsigned b = SkGetPackedB32(c);
27 
28     unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
29 
30     return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
31 }
32 
33 class SkGrayScaleColorFilter : public SkColorFilter {
34 public:
filterSpan(const SkPMColor src[],int count,SkPMColor result[]) const35     virtual void filterSpan(const SkPMColor src[], int count,
36                             SkPMColor result[]) const override {
37         for (int i = 0; i < count; i++) {
38             result[i] = rgb2gray(src[i]);
39         }
40     }
41 };
42 
43 class SkChannelMaskColorFilter : public SkColorFilter {
44 public:
SkChannelMaskColorFilter(U8CPU redMask,U8CPU greenMask,U8CPU blueMask)45     SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) {
46         fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
47     }
48 
filterSpan(const SkPMColor src[],int count,SkPMColor result[]) const49     virtual void filterSpan(const SkPMColor src[], int count,
50                             SkPMColor result[]) const override {
51         SkPMColor mask = fMask;
52         for (int i = 0; i < count; i++) {
53             result[i] = src[i] & mask;
54         }
55     }
56 
57 private:
58     SkPMColor   fMask;
59 };
60 
61 ///////////////////////////////////////////////////////////////////////////////
62 
63 #include "SkGradientShader.h"
64 #include "SkLayerRasterizer.h"
65 #include "SkBlurMaskFilter.h"
66 
67 #include "Sk2DPathEffect.h"
68 
69 class Dot2DPathEffect : public Sk2DPathEffect {
70 public:
Dot2DPathEffect(SkScalar radius,const SkMatrix & matrix,SkTDArray<SkPoint> * pts)71     Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix,
72                     SkTDArray<SkPoint>* pts)
73     : Sk2DPathEffect(matrix), fRadius(radius), fPts(pts) {}
74 
75     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect)
76 
77 protected:
begin(const SkIRect & uvBounds,SkPath * dst) const78     void begin(const SkIRect& uvBounds, SkPath* dst) const override {
79         if (fPts) {
80             fPts->reset();
81         }
82         this->INHERITED::begin(uvBounds, dst);
83     }
84 
next(const SkPoint & loc,int u,int v,SkPath * dst) const85     virtual void next(const SkPoint& loc, int u, int v,
86                       SkPath* dst) const override {
87         if (fPts) {
88             *fPts->append() = loc;
89         }
90         dst->addCircle(loc.fX, loc.fY, fRadius);
91     }
92 
flatten(SkWriteBuffer & buffer) const93     void flatten(SkWriteBuffer& buffer) const override {
94         buffer.writeMatrix(this->getMatrix());
95         buffer.writeScalar(fRadius);
96     }
97 
98 private:
99     SkScalar fRadius;
100     SkTDArray<SkPoint>* fPts;
101 
102     typedef Sk2DPathEffect INHERITED;
103 };
104 
CreateProc(SkReadBuffer & buffer)105 SkFlattenable* Dot2DPathEffect::CreateProc(SkReadBuffer& buffer) {
106     SkMatrix matrix;
107     buffer.readMatrix(&matrix);
108     return new Dot2DPathEffect(buffer.readScalar(), matrix, nullptr);
109 }
110 
111 class InverseFillPE : public SkPathEffect {
112 public:
InverseFillPE()113     InverseFillPE() {}
filterPath(SkPath * dst,const SkPath & src,SkStrokeRec *,const SkRect *) const114     virtual bool filterPath(SkPath* dst, const SkPath& src,
115                             SkStrokeRec*, const SkRect*) const override {
116         *dst = src;
117         dst->setFillType(SkPath::kInverseWinding_FillType);
118         return true;
119     }
120 
121 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const122     void toString(SkString* str) const override {
123         str->appendf("InverseFillPE: ()");
124     }
125 #endif
126 
127     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(InverseFillPE)
128 
129 private:
130     typedef SkPathEffect INHERITED;
131 };
132 
CreateProc(SkReadBuffer & buffer)133 SkFlattenable* InverseFillPE::CreateProc(SkReadBuffer& buffer) { return new InverseFillPE; }
134 
makepe(float interp,SkTDArray<SkPoint> * pts)135 static SkPathEffect* makepe(float interp, SkTDArray<SkPoint>* pts) {
136     SkMatrix    lattice;
137     SkScalar    rad = 3 + SkIntToScalar(4) * (1 - interp);
138     lattice.setScale(rad*2, rad*2, 0, 0);
139     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
140     return new Dot2DPathEffect(rad, lattice, pts);
141 }
142 
r7(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p,SkScalar interp)143 static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p, SkScalar interp) {
144     p.setPathEffect(makepe(SkScalarToFloat(interp), nullptr))->unref();
145     rastBuilder->addLayer(p);
146 #if 0
147     p.setPathEffect(new InverseFillPE())->unref();
148     p.setXfermodeMode(SkXfermode::kSrcIn_Mode);
149     p.setXfermodeMode(SkXfermode::kClear_Mode);
150     p.setAlpha((1 - interp) * 255);
151     rastBuilder->addLayer(p);
152 #endif
153 }
154 
155 typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
156 
157 #include "SkXfermode.h"
158 
apply_shader(SkPaint * paint,float scale)159 static void apply_shader(SkPaint* paint, float scale)
160 {
161     SkPaint p;
162     SkLayerRasterizer::Builder rastBuilder;
163 
164     p.setAntiAlias(true);
165     r7(&rastBuilder, p, scale);
166     paint->setRasterizer(rastBuilder.detachRasterizer())->unref();
167 
168     paint->setColor(SK_ColorBLUE);
169 }
170 
171 class ClockFaceView : public SkView {
172     SkTypeface* fFace;
173     SkScalar fInterp;
174     SkScalar fDx;
175 
176 public:
ClockFaceView()177     ClockFaceView() {
178         fFace = SkTypeface::CreateFromFile("/Users/reed/Downloads/p052024l.pfb");
179         fInterp = 0;
180         fDx = SK_Scalar1/64;
181     }
182 
~ClockFaceView()183     virtual ~ClockFaceView() {
184         SkSafeUnref(fFace);
185     }
186 
187 protected:
188     // overrides from SkEventSink
onQuery(SkEvent * evt)189     virtual bool onQuery(SkEvent* evt) {
190         if (SampleCode::TitleQ(*evt)) {
191             SampleCode::TitleR(evt, "Text Effects");
192             return true;
193         }
194         return this->INHERITED::onQuery(evt);
195     }
196 
drawBG(SkCanvas * canvas)197     void drawBG(SkCanvas* canvas) {
198 //        canvas->drawColor(0xFFDDDDDD);
199         canvas->drawColor(SK_ColorWHITE);
200     }
201 
drawdots(SkCanvas * canvas,const SkPaint & orig)202     static void drawdots(SkCanvas* canvas, const SkPaint& orig) {
203         SkTDArray<SkPoint> pts;
204         SkPathEffect* pe = makepe(0, &pts);
205 
206         SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
207         SkPath path, dstPath;
208         orig.getTextPath("9", 1, 0, 0, &path);
209         pe->filterPath(&dstPath, path, &rec, nullptr);
210 
211         SkPaint p;
212         p.setAntiAlias(true);
213         p.setStrokeWidth(10);
214         p.setColor(SK_ColorRED);
215         canvas->drawPoints(SkCanvas::kPoints_PointMode, pts.count(), pts.begin(),
216                            p);
217     }
218 
onDraw(SkCanvas * canvas)219     virtual void onDraw(SkCanvas* canvas) {
220         this->drawBG(canvas);
221 
222         SkScalar    x = SkIntToScalar(20);
223         SkScalar    y = SkIntToScalar(300);
224         SkPaint     paint;
225 
226         paint.setAntiAlias(true);
227         paint.setTextSize(SkIntToScalar(240));
228         paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
229                                                      SkTypeface::kBold));
230 
231         SkString str("9");
232 
233         paint.setTypeface(fFace);
234 
235         apply_shader(&paint, SkScalarToFloat(fInterp));
236         canvas->drawText(str.c_str(), str.size(), x, y, paint);
237 
238     //    drawdots(canvas, paint);
239 
240         if (false) {
241             fInterp += fDx;
242             if (fInterp > 1) {
243                 fInterp = 1;
244                 fDx = -fDx;
245             } else if (fInterp < 0) {
246                 fInterp = 0;
247                 fDx = -fDx;
248             }
249             this->inval(nullptr);
250         }
251     }
252 
253 private:
254     typedef SkView INHERITED;
255 };
256 
257 //////////////////////////////////////////////////////////////////////////////
258 
MyFactory()259 static SkView* MyFactory() { return new ClockFaceView; }
260 static SkViewRegister reg(MyFactory);
261