blob: f57bf385e63cf4268619d4ce1dcdf3b20758154d [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SampleCode.h"
2#include "SkCanvas.h"
3#include "SkView.h"
4#include "Sk1DPathEffect.h"
5#include "Sk2DPathEffect.h"
6#include "SkAvoidXfermode.h"
7#include "SkBlurMaskFilter.h"
8#include "SkColorFilter.h"
9#include "SkColorPriv.h"
10#include "SkCornerPathEffect.h"
11#include "SkDashPathEffect.h"
12#include "SkDiscretePathEffect.h"
13#include "SkEmbossMaskFilter.h"
14#include "SkGradientShader.h"
15#include "SkImageDecoder.h"
16#include "SkLayerRasterizer.h"
17#include "SkMath.h"
18#include "SkPath.h"
19#include "SkRegion.h"
20#include "SkShader.h"
reed@android.comaa5a7db2009-05-27 01:20:10 +000021#include "SkComposeShader.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000022#include "SkCornerPathEffect.h"
23#include "SkPathMeasure.h"
24#include "SkPicture.h"
25#include "SkRandom.h"
26#include "SkTransparentShader.h"
27#include "SkTypeface.h"
28#include "SkUnitMappers.h"
29#include "SkUtils.h"
30#include "SkXfermode.h"
31
32#include <math.h>
reed@android.com8a1c16f2008-12-17 15:59:43 +000033
34static inline SkPMColor rgb2gray(SkPMColor c)
35{
36 unsigned r = SkGetPackedR32(c);
37 unsigned g = SkGetPackedG32(c);
38 unsigned b = SkGetPackedB32(c);
39
reed@android.comf2b98d62010-12-20 18:26:13 +000040 unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
reed@android.com8a1c16f2008-12-17 15:59:43 +000041
42 return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
43}
44
45class SkGrayScaleColorFilter : public SkColorFilter {
46public:
47 virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[])
48 {
49 for (int i = 0; i < count; i++)
50 result[i] = rgb2gray(src[i]);
51 }
52};
53
54class SkChannelMaskColorFilter : public SkColorFilter {
55public:
56 SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask)
57 {
58 fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
59 }
60
61 virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[])
62 {
63 SkPMColor mask = fMask;
64 for (int i = 0; i < count; i++)
65 result[i] = src[i] & mask;
66 }
67
68private:
69 SkPMColor fMask;
70};
71
72///////////////////////////////////////////////////////////
73
74static void r0(SkLayerRasterizer* rast, SkPaint& p)
75{
76 p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
77 SkBlurMaskFilter::kNormal_BlurStyle))->unref();
78 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
79
80 p.setMaskFilter(NULL);
81 p.setStyle(SkPaint::kStroke_Style);
82 p.setStrokeWidth(SK_Scalar1);
83 rast->addLayer(p);
84
85 p.setAlpha(0x11);
86 p.setStyle(SkPaint::kFill_Style);
reed@android.com0baf1932009-06-24 12:41:42 +000087 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000088 rast->addLayer(p);
89}
90
91static void r1(SkLayerRasterizer* rast, SkPaint& p)
92{
93 rast->addLayer(p);
94
95 p.setAlpha(0x40);
reed@android.com0baf1932009-06-24 12:41:42 +000096 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000097 p.setStyle(SkPaint::kStroke_Style);
98 p.setStrokeWidth(SK_Scalar1*2);
99 rast->addLayer(p);
100}
101
102static void r2(SkLayerRasterizer* rast, SkPaint& p)
103{
104 p.setStyle(SkPaint::kStrokeAndFill_Style);
105 p.setStrokeWidth(SK_Scalar1*4);
106 rast->addLayer(p);
107
108 p.setStyle(SkPaint::kStroke_Style);
109 p.setStrokeWidth(SK_Scalar1*3/2);
reed@android.com0baf1932009-06-24 12:41:42 +0000110 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000111 rast->addLayer(p);
112}
113
114static void r3(SkLayerRasterizer* rast, SkPaint& p)
115{
116 p.setStyle(SkPaint::kStroke_Style);
117 p.setStrokeWidth(SK_Scalar1*3);
118 rast->addLayer(p);
119
120 p.setAlpha(0x20);
121 p.setStyle(SkPaint::kFill_Style);
reed@android.com0baf1932009-06-24 12:41:42 +0000122 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123 rast->addLayer(p);
124}
125
126static void r4(SkLayerRasterizer* rast, SkPaint& p)
127{
128 p.setAlpha(0x60);
129 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
130
131 p.setAlpha(0xFF);
reed@android.com0baf1932009-06-24 12:41:42 +0000132 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133 rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
134
135 p.setXfermode(NULL);
136 rast->addLayer(p);
137}
138
139static void r5(SkLayerRasterizer* rast, SkPaint& p)
140{
141 rast->addLayer(p);
142
143 p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000144 p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 rast->addLayer(p);
146}
147
148static void r6(SkLayerRasterizer* rast, SkPaint& p)
149{
150 rast->addLayer(p);
151
152 p.setAntiAlias(false);
153 SkLayerRasterizer* rast2 = new SkLayerRasterizer;
154 r5(rast2, p);
155 p.setRasterizer(rast2)->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000156 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157 rast->addLayer(p);
158}
159
160class Dot2DPathEffect : public Sk2DPathEffect {
161public:
162 Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
163 : Sk2DPathEffect(matrix), fRadius(radius) {}
164
165 virtual void flatten(SkFlattenableWriteBuffer& buffer)
166 {
167 this->INHERITED::flatten(buffer);
168
169 buffer.writeScalar(fRadius);
170 }
171 virtual Factory getFactory() { return CreateProc; }
172
173protected:
174 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst)
175 {
176 dst->addCircle(loc.fX, loc.fY, fRadius);
177 }
178
179 Dot2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer)
180 {
181 fRadius = buffer.readScalar();
182 }
183private:
184 SkScalar fRadius;
185
186 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)
187 {
188 return new Dot2DPathEffect(buffer);
189 }
190
191 typedef Sk2DPathEffect INHERITED;
192};
193
194static void r7(SkLayerRasterizer* rast, SkPaint& p)
195{
196 SkMatrix lattice;
197 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
198 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
199 p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*4, lattice))->unref();
200 rast->addLayer(p);
201}
202
203static void r8(SkLayerRasterizer* rast, SkPaint& p)
204{
205 rast->addLayer(p);
206
207 SkMatrix lattice;
208 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
209 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
210 p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000211 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 rast->addLayer(p);
213
214 p.setPathEffect(NULL);
215 p.setXfermode(NULL);
216 p.setStyle(SkPaint::kStroke_Style);
217 p.setStrokeWidth(SK_Scalar1);
218 rast->addLayer(p);
219}
220
221class Line2DPathEffect : public Sk2DPathEffect {
222public:
223 Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
224 : Sk2DPathEffect(matrix), fWidth(width) {}
225
226 virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
227 {
228 if (this->INHERITED::filterPath(dst, src, width))
229 {
230 *width = fWidth;
231 return true;
232 }
233 return false;
234 }
235
236 virtual Factory getFactory() { return CreateProc; }
237 virtual void flatten(SkFlattenableWriteBuffer& buffer)
238 {
239 this->INHERITED::flatten(buffer);
240 buffer.writeScalar(fWidth);
241 }
242protected:
243 virtual void nextSpan(int u, int v, int ucount, SkPath* dst)
244 {
245 if (ucount > 1)
246 {
247 SkPoint src[2], dstP[2];
248
249 src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
250 SkIntToScalar(v) + SK_ScalarHalf);
251 src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
252 SkIntToScalar(v) + SK_ScalarHalf);
253 this->getMatrix().mapPoints(dstP, src, 2);
254
255 dst->moveTo(dstP[0]);
256 dst->lineTo(dstP[1]);
257 }
258 }
259
deanm@chromium.org1220e1c2009-06-11 12:26:47 +0000260 Line2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261 {
262 fWidth = buffer.readScalar();
263 }
264
265private:
266 SkScalar fWidth;
267
268 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { return new Line2DPathEffect(buffer); }
269
270 typedef Sk2DPathEffect INHERITED;
271};
272
273static void r9(SkLayerRasterizer* rast, SkPaint& p)
274{
275 rast->addLayer(p);
276
277 SkMatrix lattice;
278 lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
279 lattice.postRotate(SkIntToScalar(30), 0, 0);
280 p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000281 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000282 rast->addLayer(p);
283
284 p.setPathEffect(NULL);
285 p.setXfermode(NULL);
286 p.setStyle(SkPaint::kStroke_Style);
287 p.setStrokeWidth(SK_Scalar1);
288 rast->addLayer(p);
289}
290
291typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
292
293static const raster_proc gRastProcs[] = {
294 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
295};
296
297static const struct {
298 SkColor fMul, fAdd;
299} gLightingColors[] = {
300 { 0x808080, 0x800000 }, // general case
301 { 0x707070, 0x707070 }, // no-pin case
302 { 0xFFFFFF, 0x800000 }, // just-add case
303 { 0x808080, 0x000000 }, // just-mul case
304 { 0xFFFFFF, 0x000000 } // identity case
305};
306
307static unsigned color_dist16(uint16_t a, uint16_t b)
308{
309 unsigned dr = SkAbs32(SkPacked16ToR32(a) - SkPacked16ToR32(b));
310 unsigned dg = SkAbs32(SkPacked16ToG32(a) - SkPacked16ToG32(b));
311 unsigned db = SkAbs32(SkPacked16ToB32(a) - SkPacked16ToB32(b));
312
313 return SkMax32(dr, SkMax32(dg, db));
314}
315
316static unsigned scale_dist(unsigned dist, unsigned scale)
317{
318 dist >>= 6;
319 dist = (dist << 2) | dist;
320 dist = (dist << 4) | dist;
321 return dist;
322
323// return SkAlphaMul(dist, scale);
324}
325
326static void apply_shader(SkPaint* paint, int index)
327{
328 raster_proc proc = gRastProcs[index];
329 if (proc)
330 {
331 SkPaint p;
332 SkLayerRasterizer* rast = new SkLayerRasterizer;
333
334 p.setAntiAlias(true);
335 proc(rast, p);
336 paint->setRasterizer(rast)->unref();
337 }
338
339#if 1
340 SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
341 paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
342 paint->setColor(SK_ColorBLUE);
343#endif
344}
345
reed@android.com8a1c16f2008-12-17 15:59:43 +0000346class DemoView : public SkView {
347public:
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000348 DemoView() {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000349
350protected:
351 // overrides from SkEventSink
352 virtual bool onQuery(SkEvent* evt)
353 {
354 if (SampleCode::TitleQ(*evt))
355 {
356 SampleCode::TitleR(evt, "Demo");
357 return true;
358 }
359 return this->INHERITED::onQuery(evt);
360 }
361
362 virtual bool onClick(Click* click)
363 {
364 return this->INHERITED::onClick(click);
365 }
366
367 void makePath(SkPath& path)
368 {
369 path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
370 SkPath::kCCW_Direction);
371 for (int index = 0; index < 10; index++) {
372 SkScalar x = SkFloatToScalar(cos(index / 10.0f * 2 * 3.1415925358f));
373 SkScalar y = SkFloatToScalar(sin(index / 10.0f * 2 * 3.1415925358f));
374 x *= index & 1 ? 7 : 14;
375 y *= index & 1 ? 7 : 14;
376 x += SkIntToScalar(20);
377 y += SkIntToScalar(20);
378 if (index == 0)
379 path.moveTo(x, y);
380 else
381 path.lineTo(x, y);
382 }
383 path.close();
384 }
385
386 virtual void onDraw(SkCanvas* canvas)
387 {
388 canvas->drawColor(SK_ColorWHITE);
389 canvas->save();
390 drawPicture(canvas, 0);
391 canvas->restore();
392
393 {
394 SkPicture picture;
395 SkCanvas* record = picture.beginRecording(320, 480);
396 drawPicture(record, 120);
397 canvas->translate(0, SkIntToScalar(120));
398
399 SkRect clip;
400 clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
401 do {
402 canvas->save();
403 canvas->clipRect(clip);
404 picture.draw(canvas);
405 canvas->restore();
406 if (clip.fRight < SkIntToScalar(320))
407 clip.offset(SkIntToScalar(160), 0);
408 else if (clip.fBottom < SkIntToScalar(480))
409 clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
410 else
411 break;
412 } while (true);
413 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000414 }
415
416 void drawPicture(SkCanvas* canvas, int spriteOffset)
417 {
418 SkMatrix matrix; matrix.reset();
419 SkPaint paint;
420 SkPath path;
421 SkPoint start = {0, 0};
422 SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
423 SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
424 SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
425 SkScalar left = 0, top = 0, x = 0, y = 0;
reed@google.com261b8e22011-04-14 17:53:24 +0000426 size_t index;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000427
428 char ascii[] = "ascii...";
429 size_t asciiLength = sizeof(ascii) - 1;
430 char utf8[] = "utf8" "\xe2\x80\xa6";
431 short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
432 short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
433
434 makePath(path);
435 SkTDArray<SkPoint>(pos);
436 pos.setCount(asciiLength);
437 for (index = 0; index < asciiLength; index++)
438 pos[index].set(SkIntToScalar(index * 10), SkIntToScalar(index * 2));
439 SkTDArray<SkPoint>(pos2);
440 pos2.setCount(asciiLength);
441 for (index = 0; index < asciiLength; index++)
442 pos2[index].set(SkIntToScalar(index * 10), SkIntToScalar(20));
443
444 // shaders
445 SkPoint linearPoints[] = { 0, 0, SkIntToScalar(40), SkIntToScalar(40) };
446 SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
447 SkScalar* linearPos = NULL;
448 int linearCount = 2;
449 SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
450 SkUnitMapper* linearMapper = new SkDiscreteMapper(3);
451 SkAutoUnref unmapLinearMapper(linearMapper);
452 SkShader* linear = SkGradientShader::CreateLinear(linearPoints,
453 linearColors, linearPos, linearCount, linearMode, linearMapper);
454
455 SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
456 SkScalar radialRadius = SkIntToScalar(25);
457 SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
458 SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
459 int radialCount = 3;
460 SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
461 SkUnitMapper* radialMapper = new SkCosineMapper();
462 SkAutoUnref unmapRadialMapper(radialMapper);
463 SkShader* radial = SkGradientShader::CreateRadial(radialCenter,
464 radialRadius, radialColors, radialPos, radialCount,
465 radialMode, radialMapper);
466
467 SkTransparentShader* transparentShader = new SkTransparentShader();
468 SkEmbossMaskFilter::Light light;
469 light.fDirection[0] = SK_Scalar1/2;
470 light.fDirection[1] = SK_Scalar1/2;
471 light.fDirection[2] = SK_Scalar1/3;
472 light.fAmbient = 0x48;
473 light.fSpecular = 0x80;
474 SkScalar radius = SkIntToScalar(12)/5;
475 SkEmbossMaskFilter* embossFilter = new SkEmbossMaskFilter(light,
476 radius);
477
reed@android.com048522d2009-06-23 12:19:41 +0000478 SkXfermode* xfermode = SkXfermode::Create(SkXfermode::kXor_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479 SkColorFilter* lightingFilter = SkColorFilter::CreateLightingFilter(
480 0xff89bc45, 0xff112233);
481
482 canvas->save();
483 canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
484 paint.setFlags(SkPaint::kAntiAlias_Flag | SkPaint::kFilterBitmap_Flag);
485 // !!! draw through a clip
486 paint.setColor(SK_ColorLTGRAY);
487 paint.setStyle(SkPaint::kFill_Style);
488 SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
489 canvas->clipRect(clip);
490 paint.setShader(SkShader::CreateBitmapShader(fTx,
491 SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode))->unref();
492 canvas->drawPaint(paint);
493 canvas->save();
494
495 // line (exercises xfermode, colorShader, colorFilter, filterShader)
496 paint.setColor(SK_ColorGREEN);
497 paint.setStrokeWidth(SkIntToScalar(10));
498 paint.setStyle(SkPaint::kStroke_Style);
499 paint.setXfermode(xfermode)->unref();
500 paint.setColorFilter(lightingFilter)->unref();
501 canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
502 paint.setXfermode(NULL);
503 paint.setColorFilter(NULL);
504
505 // rectangle
506 paint.setStyle(SkPaint::kFill_Style);
507 canvas->translate(SkIntToScalar(50), 0);
508 paint.setColor(SK_ColorYELLOW);
509 paint.setShader(linear)->unref();
510 paint.setPathEffect(pathEffectTest())->unref();
511 canvas->drawRect(rect, paint);
512 paint.setPathEffect(NULL);
513
514 // circle w/ emboss & transparent (exercises 3dshader)
515 canvas->translate(SkIntToScalar(50), 0);
516 paint.setMaskFilter(embossFilter)->unref();
517 canvas->drawOval(rect, paint);
518 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
519 paint.setShader(transparentShader)->unref();
520 canvas->drawOval(rect, paint);
521 canvas->translate(0, SkIntToScalar(-10));
522
523 // path
524 canvas->translate(SkIntToScalar(50), 0);
525 paint.setColor(SK_ColorRED);
526 paint.setStyle(SkPaint::kStroke_Style);
527 paint.setStrokeWidth(SkIntToScalar(5));
528 paint.setShader(radial)->unref();
529 paint.setMaskFilter(NULL);
530 canvas->drawPath(path, paint);
531
532 paint.setShader(NULL);
533 // bitmap, sprite
534 canvas->translate(SkIntToScalar(50), 0);
535 paint.setStyle(SkPaint::kFill_Style);
536 canvas->drawBitmap(fBug, left, top, &paint);
537 canvas->translate(SkIntToScalar(30), 0);
538 canvas->drawSprite(fTb,
539 SkScalarRound(canvas->getTotalMatrix().getTranslateX()),
540 spriteOffset + 10, &paint);
541
542 canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
543 paint.setShader(shaderTest())->unref(); // test compose shader
544 canvas->drawRect(rect2, paint);
545 paint.setShader(NULL);
546
547 canvas->restore();
548 // text
549 canvas->translate(0, SkIntToScalar(60));
550 canvas->save();
551 paint.setColor(SK_ColorGRAY);
552 canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
553 canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
554
555 canvas->translate(SkIntToScalar(50), 0);
556 paint.setColor(SK_ColorCYAN);
557 canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
558
559 canvas->translate(SkIntToScalar(30), 0);
560 paint.setColor(SK_ColorMAGENTA);
561 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
562 matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
563 canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
564 canvas->translate(0, SkIntToScalar(20));
565 canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
566 canvas->restore();
567
568 canvas->translate(0, SkIntToScalar(60));
569 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
570 canvas->restore();
571 }
572
573 /*
574./SkColorFilter.h:25:class SkColorFilter : public SkFlattenable { -- abstract
575 static SkColorFilter* CreatXfermodeFilter() *** untested ***
576 static SkColorFilter* CreatePorterDuffFilter() *** untested ***
577 static SkColorFilter* CreateLightingFilter() -- tested
578./SkDrawLooper.h:9:class SkDrawLooper : public SkFlattenable { -- virtually abstract
579 ./SkBlurDrawLooper.h:9:class SkBlurDrawLooper : public SkDrawLooper { *** untested ***
580./SkMaskFilter.h:41:class SkMaskFilter : public SkFlattenable { -- abstract chmod +w .h
581 ./SkEmbossMaskFilter.h:27:class SkEmbossMaskFilter : public SkMaskFilter { -- tested
582./SkPathEffect.h:33:class SkPathEffect : public SkFlattenable { -- abstract
583 ./Sk1DPathEffect.h:27:class Sk1DPathEffect : public SkPathEffect { -- abstract
584 ./Sk1DPathEffect.h:48:class SkPath1DPathEffect : public Sk1DPathEffect { -- tested
585 ./Sk2DPathEffect.h:25:class Sk2DPathEffect : public SkPathEffect { *** untested ***
586 ./SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect { *** untested ***
587 ./SkDashPathEffect.h:27:class SkDashPathEffect : public SkPathEffect {
588 ./SkDiscretePathEffect.h:27:class SkDiscretePathEffect : public SkPathEffect {
589 ./SkPaint.h:760:class SkStrokePathEffect : public SkPathEffect {
590 ./SkPathEffect.h:58:class SkPairPathEffect : public SkPathEffect {
591 ./SkPathEffect.h:78:class SkComposePathEffect : public SkPairPathEffect {
592 ./SkPathEffect.h:114:class SkSumPathEffect : public SkPairPathEffect {
593./SkRasterizer.h:29:class SkRasterizer : public SkFlattenable {
594 ./SkLayerRasterizer.h:27:class SkLayerRasterizer : public SkRasterizer {
595./SkShader.h:36:class SkShader : public SkFlattenable {
596 ./SkColorFilter.h:59:class SkFilterShader : public SkShader {
597 ./SkColorShader.h:26:class SkColorShader : public SkShader {
598 ./SkShaderExtras.h:31:class SkComposeShader : public SkShader {
599 ./SkTransparentShader.h:23:class SkTransparentShader : public SkShader {
600./SkUnitMapper.h:24:class SkUnitMapper : public SkFlattenable {
601 ./SkUnitMapper.h:33:class SkDiscreteMapper : public SkUnitMapper {
602 ./SkUnitMapper.h:51:class SkFlipCosineMapper : public SkUnitMapper {
603./SkXfermode.h:32:class SkXfermode : public SkFlattenable {
604 ./SkAvoidXfermode.h:28:class SkAvoidXfermode : public SkXfermode { *** not done *** chmod +w .h .cpp
605 ./SkXfermode.h:54:class SkProcXfermode : public SkXfermode {
606 */
607
608 /*
609./SkBlurMaskFilter.h:25:class SkBlurMaskFilter {
610 chmod +w SkBlurMaskFilter.cpp
611./SkGradientShader.h:30:class SkGradientShader {
612 */
613 // save layer, bounder, looper
614 // matrix
615 // clip /path/region
616 // bitmap proc shader ?
617
618/* untested:
619SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect {
620*/
621
622 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
623 {
624 fClickPt.set(x, y);
625 this->inval(NULL);
626 return this->INHERITED::onFindClickHandler(x, y);
627 }
628
629 SkPathEffect* pathEffectTest()
630 {
631 static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
632 SkScalar gPhase = 0;
633 SkPath path;
634 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
635 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
636 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
637 path.close();
638 path.offset(SkIntToScalar(-6), 0);
639 SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12),
640 gPhase, SkPath1DPathEffect::kRotate_Style);
641 SkPathEffect* inner = new SkDiscretePathEffect(SkIntToScalar(2),
642 SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
643 SkPathEffect* result = new SkComposePathEffect(outer, inner);
644 outer->unref();
645 inner->unref();
646 return result;
647 }
648
649 SkPathEffect* pathEffectTest2() // unsure this works (has no visible effect)
650 {
651 SkPathEffect* outer = new SkStrokePathEffect(SkIntToScalar(4),
652 SkPaint::kStroke_Style, SkPaint::kMiter_Join, SkPaint::kButt_Cap);
653 static const SkScalar intervals[] = {SkIntToScalar(1), SkIntToScalar(2),
654 SkIntToScalar(2), SkIntToScalar(1)};
655 SkPathEffect* inner = new SkDashPathEffect(intervals,
656 sizeof(intervals) / sizeof(intervals[0]), 0);
657 SkPathEffect* result = new SkSumPathEffect(outer, inner);
658 outer->unref();
659 inner->unref();
660 return result;
661 }
662
663 SkShader* shaderTest()
664 {
665 SkPoint pts[] = {0, 0, SkIntToScalar(100), 0 };
666 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
667 SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL,
668 2, SkShader::kClamp_TileMode);
669 pts[1].set(0, SkIntToScalar(100));
670 SkColor colors2[] = {SK_ColorBLACK, SkColorSetARGB(0x80, 0, 0, 0)};
671 SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors2, NULL,
672 2, SkShader::kClamp_TileMode);
reed@android.com048522d2009-06-23 12:19:41 +0000673 SkXfermode* mode = SkXfermode::Create(SkXfermode::kDstIn_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000674 SkShader* result = new SkComposeShader(shaderA, shaderB, mode);
675 shaderA->unref();
676 shaderB->unref();
677 mode->unref();
678 return result;
679 }
680
681 virtual void startTest() {
682 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
683 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
684 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/05psp04.gif", &fTx);
685 }
686
687 void drawRaster(SkCanvas* canvas)
688 {
689 for (int index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
690 drawOneRaster(canvas);
691 }
692
693 void drawOneRaster(SkCanvas* canvas)
694 {
695 canvas->save();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000696
697 SkScalar x = SkIntToScalar(20);
698 SkScalar y = SkIntToScalar(40);
699 SkPaint paint;
700
701 paint.setAntiAlias(true);
702 paint.setTextSize(SkIntToScalar(48));
reed@android.comaa5a7db2009-05-27 01:20:10 +0000703 paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
704 SkTypeface::kBold));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000705
706 SkString str("GOOGLE");
707
708 for (int i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++)
709 {
710 apply_shader(&paint, i);
711
712 // paint.setMaskFilter(NULL);
713 // paint.setColor(SK_ColorBLACK);
714
715#if 01
716 int index = i % SK_ARRAY_COUNT(gLightingColors);
717 paint.setColorFilter(SkColorFilter::CreateLightingFilter(
718 gLightingColors[index].fMul,
719 gLightingColors[index].fAdd))->unref();
720#endif
721
722 canvas->drawText(str.c_str(), str.size(), x, y, paint);
723 SkRect oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
724 paint.setStyle(SkPaint::kStroke_Style);
725 canvas->drawOval(oval, paint);
726 paint.setStyle(SkPaint::kFill_Style);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000727
728 y += paint.getFontSpacing();
729 }
730
731 canvas->restore();
732
reed@android.com6b82d1a2009-06-03 02:35:01 +0000733 if (1) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000734 SkAvoidXfermode mode(SK_ColorWHITE, 0xFF,
735 SkAvoidXfermode::kTargetColor_Mode);
736 SkPaint paint;
737 x += SkIntToScalar(20);
738 SkRect r = { x, 0, x + SkIntToScalar(360), SkIntToScalar(700) };
739 paint.setXfermode(&mode);
740 paint.setColor(SK_ColorGREEN);
741 paint.setAntiAlias(true);
742 canvas->drawOval(r, paint);
743 }
744 }
745
746private:
747 SkPoint fClickPt;
748 SkBitmap fBug, fTb, fTx;
749 typedef SkView INHERITED;
750};
751
752//////////////////////////////////////////////////////////////////////////////
753
754static SkView* MyFactory() { return new DemoView; }
755static SkViewRegister reg(MyFactory);
756