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 "SkGradientShader.h"
12 #include "SkPath.h"
13 #include "SkRegion.h"
14 #include "SkShader.h"
15 #include "SkUtils.h"
16 #include "SkColorPriv.h"
17 #include "SkColorFilter.h"
18 #include "SkTypeface.h"
19 #include "SkAvoidXfermode.h"
20
rgb2gray(SkPMColor c)21 static inline SkPMColor rgb2gray(SkPMColor c) {
22 unsigned r = SkGetPackedR32(c);
23 unsigned g = SkGetPackedG32(c);
24 unsigned b = SkGetPackedB32(c);
25
26 unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
27
28 return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
29 }
30
31 class SkGrayScaleColorFilter : public SkColorFilter {
32 public:
filterSpan(const SkPMColor src[],int count,SkPMColor result[])33 virtual void filterSpan(const SkPMColor src[], int count,
34 SkPMColor result[]) {
35 for (int i = 0; i < count; i++) {
36 result[i] = rgb2gray(src[i]);
37 }
38 }
39 };
40
41 class SkChannelMaskColorFilter : public SkColorFilter {
42 public:
SkChannelMaskColorFilter(U8CPU redMask,U8CPU greenMask,U8CPU blueMask)43 SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) {
44 fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
45 }
46
filterSpan(const SkPMColor src[],int count,SkPMColor result[])47 virtual void filterSpan(const SkPMColor src[], int count,
48 SkPMColor result[]) {
49 SkPMColor mask = fMask;
50 for (int i = 0; i < count; i++) {
51 result[i] = src[i] & mask;
52 }
53 }
54
55 private:
56 SkPMColor fMask;
57 };
58
59 ///////////////////////////////////////////////////////////
60
61 #include "SkGradientShader.h"
62 #include "SkLayerRasterizer.h"
63 #include "SkBlurMaskFilter.h"
64
r0(SkLayerRasterizer * rast,SkPaint & p)65 static void r0(SkLayerRasterizer* rast, SkPaint& p) {
66 p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
67 SkBlurMaskFilter::kNormal_BlurStyle))->unref();
68 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
69
70 p.setMaskFilter(NULL);
71 p.setStyle(SkPaint::kStroke_Style);
72 p.setStrokeWidth(SK_Scalar1);
73 rast->addLayer(p);
74
75 p.setAlpha(0x11);
76 p.setStyle(SkPaint::kFill_Style);
77 p.setXfermodeMode(SkXfermode::kSrc_Mode);
78 rast->addLayer(p);
79 }
80
r1(SkLayerRasterizer * rast,SkPaint & p)81 static void r1(SkLayerRasterizer* rast, SkPaint& p) {
82 rast->addLayer(p);
83
84 p.setAlpha(0x40);
85 p.setXfermodeMode(SkXfermode::kSrc_Mode);
86 p.setStyle(SkPaint::kStroke_Style);
87 p.setStrokeWidth(SK_Scalar1*2);
88 rast->addLayer(p);
89 }
90
r2(SkLayerRasterizer * rast,SkPaint & p)91 static void r2(SkLayerRasterizer* rast, SkPaint& p) {
92 p.setStyle(SkPaint::kStrokeAndFill_Style);
93 p.setStrokeWidth(SK_Scalar1*4);
94 rast->addLayer(p);
95
96 p.setStyle(SkPaint::kStroke_Style);
97 p.setStrokeWidth(SK_Scalar1*3/2);
98 p.setXfermodeMode(SkXfermode::kClear_Mode);
99 rast->addLayer(p);
100 }
101
r3(SkLayerRasterizer * rast,SkPaint & p)102 static void r3(SkLayerRasterizer* rast, SkPaint& p) {
103 p.setStyle(SkPaint::kStroke_Style);
104 p.setStrokeWidth(SK_Scalar1*3);
105 rast->addLayer(p);
106
107 p.setAlpha(0x20);
108 p.setStyle(SkPaint::kFill_Style);
109 p.setXfermodeMode(SkXfermode::kSrc_Mode);
110 rast->addLayer(p);
111 }
112
r4(SkLayerRasterizer * rast,SkPaint & p)113 static void r4(SkLayerRasterizer* rast, SkPaint& p) {
114 p.setAlpha(0x60);
115 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
116
117 p.setAlpha(0xFF);
118 p.setXfermodeMode(SkXfermode::kClear_Mode);
119 rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
120
121 p.setXfermode(NULL);
122 rast->addLayer(p);
123 }
124
125 #include "SkDiscretePathEffect.h"
126
r5(SkLayerRasterizer * rast,SkPaint & p)127 static void r5(SkLayerRasterizer* rast, SkPaint& p) {
128 rast->addLayer(p);
129
130 p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
131 p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
132 rast->addLayer(p);
133 }
134
r6(SkLayerRasterizer * rast,SkPaint & p)135 static void r6(SkLayerRasterizer* rast, SkPaint& p) {
136 rast->addLayer(p);
137
138 p.setAntiAlias(false);
139 SkLayerRasterizer* rast2 = new SkLayerRasterizer;
140 r5(rast2, p);
141 p.setRasterizer(rast2)->unref();
142 p.setXfermodeMode(SkXfermode::kClear_Mode);
143 rast->addLayer(p);
144 }
145
146 #include "Sk2DPathEffect.h"
147
MakeDotEffect(SkScalar radius,const SkMatrix & matrix)148 static SkPathEffect* MakeDotEffect(SkScalar radius, const SkMatrix& matrix) {
149 SkPath path;
150 path.addCircle(0, 0, radius);
151 return new SkPath2DPathEffect(matrix, path);
152 }
153
r7(SkLayerRasterizer * rast,SkPaint & p)154 static void r7(SkLayerRasterizer* rast, SkPaint& p) {
155 SkMatrix lattice;
156 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
157 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
158 p.setPathEffect(MakeDotEffect(SK_Scalar1*4, lattice))->unref();
159 rast->addLayer(p);
160 }
161
r8(SkLayerRasterizer * rast,SkPaint & p)162 static void r8(SkLayerRasterizer* rast, SkPaint& p) {
163 rast->addLayer(p);
164
165 SkMatrix lattice;
166 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
167 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
168 p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice))->unref();
169 p.setXfermodeMode(SkXfermode::kClear_Mode);
170 rast->addLayer(p);
171
172 p.setPathEffect(NULL);
173 p.setXfermode(NULL);
174 p.setStyle(SkPaint::kStroke_Style);
175 p.setStrokeWidth(SK_Scalar1);
176 rast->addLayer(p);
177 }
178
179 class Line2DPathEffect : public Sk2DPathEffect {
180 public:
Line2DPathEffect(SkScalar width,const SkMatrix & matrix)181 Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
182 : Sk2DPathEffect(matrix), fWidth(width) {}
183
filterPath(SkPath * dst,const SkPath & src,SkScalar * width)184 virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
185 if (this->INHERITED::filterPath(dst, src, width)) {
186 *width = fWidth;
187 return true;
188 }
189 return false;
190 }
191
getFactory()192 virtual Factory getFactory() { return CreateProc; }
flatten(SkFlattenableWriteBuffer & buffer)193 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
194 this->INHERITED::flatten(buffer);
195 buffer.writeScalar(fWidth);
196 }
197
198 protected:
nextSpan(int u,int v,int ucount,SkPath * dst)199 virtual void nextSpan(int u, int v, int ucount, SkPath* dst) {
200 if (ucount > 1) {
201 SkPoint src[2], dstP[2];
202
203 src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
204 SkIntToScalar(v) + SK_ScalarHalf);
205 src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
206 SkIntToScalar(v) + SK_ScalarHalf);
207 this->getMatrix().mapPoints(dstP, src, 2);
208
209 dst->moveTo(dstP[0]);
210 dst->lineTo(dstP[1]);
211 }
212 }
213
Line2DPathEffect(SkFlattenableReadBuffer & buffer)214 Line2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer) {
215 fWidth = buffer.readScalar();
216 }
217
218 private:
219 SkScalar fWidth;
220
CreateProc(SkFlattenableReadBuffer & buffer)221 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
222 return new Line2DPathEffect(buffer);
223 }
224
225 typedef Sk2DPathEffect INHERITED;
226 };
227
r9(SkLayerRasterizer * rast,SkPaint & p)228 static void r9(SkLayerRasterizer* rast, SkPaint& p) {
229 rast->addLayer(p);
230
231 SkMatrix lattice;
232 lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
233 lattice.postRotate(SkIntToScalar(30), 0, 0);
234 p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
235 p.setXfermodeMode(SkXfermode::kClear_Mode);
236 rast->addLayer(p);
237
238 p.setPathEffect(NULL);
239 p.setXfermode(NULL);
240 p.setStyle(SkPaint::kStroke_Style);
241 p.setStrokeWidth(SK_Scalar1);
242 rast->addLayer(p);
243 }
244
245 typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
246
247 static const raster_proc gRastProcs[] = {
248 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
249 };
250
251 static const struct {
252 SkColor fMul, fAdd;
253 } gLightingColors[] = {
254 { 0x808080, 0x800000 }, // general case
255 { 0x707070, 0x707070 }, // no-pin case
256 { 0xFFFFFF, 0x800000 }, // just-add case
257 { 0x808080, 0x000000 }, // just-mul case
258 { 0xFFFFFF, 0x000000 } // identity case
259 };
260
261 #include "SkXfermode.h"
262
color_dist16(uint16_t a,uint16_t b)263 static unsigned color_dist16(uint16_t a, uint16_t b) {
264 unsigned dr = SkAbs32(SkPacked16ToR32(a) - SkPacked16ToR32(b));
265 unsigned dg = SkAbs32(SkPacked16ToG32(a) - SkPacked16ToG32(b));
266 unsigned db = SkAbs32(SkPacked16ToB32(a) - SkPacked16ToB32(b));
267
268 return SkMax32(dr, SkMax32(dg, db));
269 }
270
scale_dist(unsigned dist,unsigned scale)271 static unsigned scale_dist(unsigned dist, unsigned scale) {
272 dist >>= 6;
273 dist = (dist << 2) | dist;
274 dist = (dist << 4) | dist;
275 return dist;
276
277 // return SkAlphaMul(dist, scale);
278 }
279
apply_shader(SkPaint * paint,int index)280 static void apply_shader(SkPaint* paint, int index) {
281 raster_proc proc = gRastProcs[index];
282 if (proc)
283 {
284 SkPaint p;
285 SkLayerRasterizer* rast = new SkLayerRasterizer;
286
287 p.setAntiAlias(true);
288 proc(rast, p);
289 paint->setRasterizer(rast)->unref();
290 }
291
292 #if 0
293 SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
294 paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
295 #endif
296 paint->setColor(SK_ColorBLUE);
297 }
298
299 static int gRastIndex;
300
301 class TextEffectView : public SampleView {
302 SkTypeface* fFace;
303 public:
TextEffectView()304 TextEffectView() {
305 fFace = SkTypeface::CreateFromFile("/Users/reed/Downloads/p052024l.pfb");
306 }
307
~TextEffectView()308 virtual ~TextEffectView() {
309 SkSafeUnref(fFace);
310 }
311
312 protected:
313 // overrides from SkEventSink
onQuery(SkEvent * evt)314 virtual bool onQuery(SkEvent* evt) {
315 if (SampleCode::TitleQ(*evt)) {
316 SampleCode::TitleR(evt, "Text Effects");
317 return true;
318 }
319 return this->INHERITED::onQuery(evt);
320 }
321
onDrawContent(SkCanvas * canvas)322 virtual void onDrawContent(SkCanvas* canvas) {
323 canvas->save();
324 // canvas->scale(SK_Scalar1*2, SK_Scalar1*2, 0, 0);
325
326 SkPaint paint;
327
328 paint.setAntiAlias(true);
329 paint.setTextSize(SkIntToScalar(56));
330 paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
331 SkTypeface::kBold));
332
333 SkScalar x = SkIntToScalar(20);
334 SkScalar y = paint.getTextSize();
335
336 SkString str("TextEffects");
337
338 paint.setTypeface(fFace);
339
340 for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
341 apply_shader(&paint, i);
342
343 // paint.setMaskFilter(NULL);
344 // paint.setColor(SK_ColorBLACK);
345
346 #if 1
347 int index = i % SK_ARRAY_COUNT(gLightingColors);
348 paint.setColorFilter(SkColorFilter::CreateLightingFilter(
349 gLightingColors[index].fMul,
350 gLightingColors[index].fAdd))->unref();
351 #endif
352
353 canvas->drawText(str.c_str(), str.size(), x, y, paint);
354
355 y += paint.getFontSpacing();
356 }
357
358 canvas->restore();
359 }
360
onFindClickHandler(SkScalar x,SkScalar y)361 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
362 gRastIndex = (gRastIndex + 1) % SK_ARRAY_COUNT(gRastProcs);
363 this->inval(NULL);
364
365 return this->INHERITED::onFindClickHandler(x, y);
366 }
367
onClick(Click * click)368 virtual bool onClick(Click* click) {
369 return this->INHERITED::onClick(click);
370 }
371
372 private:
373 typedef SampleView INHERITED;
374 };
375
376 //////////////////////////////////////////////////////////////////////////////
377
MyFactory()378 static SkView* MyFactory() { return new TextEffectView; }
379 static SkViewRegister reg(MyFactory);
380
381