blob: 75d1a317ca945e058b0666c2fd50691e1c6b0e05 [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
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000034static inline SkPMColor rgb2gray(SkPMColor c) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000035 unsigned r = SkGetPackedR32(c);
36 unsigned g = SkGetPackedG32(c);
37 unsigned b = SkGetPackedB32(c);
38
reed@android.comf2b98d62010-12-20 18:26:13 +000039 unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
reed@android.com8a1c16f2008-12-17 15:59:43 +000040
41 return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
42}
43
44class SkGrayScaleColorFilter : public SkColorFilter {
45public:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000046 virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000047 for (int i = 0; i < count; i++)
48 result[i] = rgb2gray(src[i]);
49 }
50};
51
52class SkChannelMaskColorFilter : public SkColorFilter {
53public:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000054 SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000055 fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
56 }
57
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000058 virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000059 SkPMColor mask = fMask;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000060 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000061 result[i] = src[i] & mask;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000062 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000063 }
64
65private:
66 SkPMColor fMask;
67};
68
69///////////////////////////////////////////////////////////
70
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000071static void r0(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000072 p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
73 SkBlurMaskFilter::kNormal_BlurStyle))->unref();
74 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
75
76 p.setMaskFilter(NULL);
77 p.setStyle(SkPaint::kStroke_Style);
78 p.setStrokeWidth(SK_Scalar1);
79 rast->addLayer(p);
80
81 p.setAlpha(0x11);
82 p.setStyle(SkPaint::kFill_Style);
reed@android.com0baf1932009-06-24 12:41:42 +000083 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000084 rast->addLayer(p);
85}
86
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000087static void r1(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000088 rast->addLayer(p);
89
90 p.setAlpha(0x40);
reed@android.com0baf1932009-06-24 12:41:42 +000091 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000092 p.setStyle(SkPaint::kStroke_Style);
93 p.setStrokeWidth(SK_Scalar1*2);
94 rast->addLayer(p);
95}
96
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000097static void r2(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000098 p.setStyle(SkPaint::kStrokeAndFill_Style);
99 p.setStrokeWidth(SK_Scalar1*4);
100 rast->addLayer(p);
101
102 p.setStyle(SkPaint::kStroke_Style);
103 p.setStrokeWidth(SK_Scalar1*3/2);
reed@android.com0baf1932009-06-24 12:41:42 +0000104 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 rast->addLayer(p);
106}
107
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000108static void r3(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109 p.setStyle(SkPaint::kStroke_Style);
110 p.setStrokeWidth(SK_Scalar1*3);
111 rast->addLayer(p);
112
113 p.setAlpha(0x20);
114 p.setStyle(SkPaint::kFill_Style);
reed@android.com0baf1932009-06-24 12:41:42 +0000115 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 rast->addLayer(p);
117}
118
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000119static void r4(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120 p.setAlpha(0x60);
121 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
122
123 p.setAlpha(0xFF);
reed@android.com0baf1932009-06-24 12:41:42 +0000124 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125 rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
126
127 p.setXfermode(NULL);
128 rast->addLayer(p);
129}
130
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000131static void r5(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 rast->addLayer(p);
133
134 p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000135 p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136 rast->addLayer(p);
137}
138
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000139static void r6(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140 rast->addLayer(p);
141
142 p.setAntiAlias(false);
143 SkLayerRasterizer* rast2 = new SkLayerRasterizer;
144 r5(rast2, p);
145 p.setRasterizer(rast2)->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000146 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147 rast->addLayer(p);
148}
149
150class Dot2DPathEffect : public Sk2DPathEffect {
151public:
152 Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
153 : Sk2DPathEffect(matrix), fRadius(radius) {}
154
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000155 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156 this->INHERITED::flatten(buffer);
157
158 buffer.writeScalar(fRadius);
159 }
160 virtual Factory getFactory() { return CreateProc; }
161
162protected:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000163 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164 dst->addCircle(loc.fX, loc.fY, fRadius);
165 }
166
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000167 Dot2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 fRadius = buffer.readScalar();
169 }
170private:
171 SkScalar fRadius;
172
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000173 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174 return new Dot2DPathEffect(buffer);
175 }
176
177 typedef Sk2DPathEffect INHERITED;
178};
179
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000180static void r7(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181 SkMatrix lattice;
182 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
183 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
184 p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*4, lattice))->unref();
185 rast->addLayer(p);
186}
187
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000188static void r8(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189 rast->addLayer(p);
190
191 SkMatrix lattice;
192 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
193 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
194 p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000195 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196 rast->addLayer(p);
197
198 p.setPathEffect(NULL);
199 p.setXfermode(NULL);
200 p.setStyle(SkPaint::kStroke_Style);
201 p.setStrokeWidth(SK_Scalar1);
202 rast->addLayer(p);
203}
204
205class Line2DPathEffect : public Sk2DPathEffect {
206public:
207 Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
208 : Sk2DPathEffect(matrix), fWidth(width) {}
209
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000210 virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
211 if (this->INHERITED::filterPath(dst, src, width)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 *width = fWidth;
213 return true;
214 }
215 return false;
216 }
217
218 virtual Factory getFactory() { return CreateProc; }
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000219 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220 this->INHERITED::flatten(buffer);
221 buffer.writeScalar(fWidth);
222 }
223protected:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000224 virtual void nextSpan(int u, int v, int ucount, SkPath* dst) {
225 if (ucount > 1) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226 SkPoint src[2], dstP[2];
227
228 src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
229 SkIntToScalar(v) + SK_ScalarHalf);
230 src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
231 SkIntToScalar(v) + SK_ScalarHalf);
232 this->getMatrix().mapPoints(dstP, src, 2);
233
234 dst->moveTo(dstP[0]);
235 dst->lineTo(dstP[1]);
236 }
237 }
238
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000239 Line2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000240 fWidth = buffer.readScalar();
241 }
242
243private:
244 SkScalar fWidth;
245
246 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { return new Line2DPathEffect(buffer); }
247
248 typedef Sk2DPathEffect INHERITED;
249};
250
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000251static void r9(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000252 rast->addLayer(p);
253
254 SkMatrix lattice;
255 lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
256 lattice.postRotate(SkIntToScalar(30), 0, 0);
257 p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000258 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259 rast->addLayer(p);
260
261 p.setPathEffect(NULL);
262 p.setXfermode(NULL);
263 p.setStyle(SkPaint::kStroke_Style);
264 p.setStrokeWidth(SK_Scalar1);
265 rast->addLayer(p);
266}
267
268typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
269
270static const raster_proc gRastProcs[] = {
271 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
272};
273
274static const struct {
275 SkColor fMul, fAdd;
276} gLightingColors[] = {
277 { 0x808080, 0x800000 }, // general case
278 { 0x707070, 0x707070 }, // no-pin case
279 { 0xFFFFFF, 0x800000 }, // just-add case
280 { 0x808080, 0x000000 }, // just-mul case
281 { 0xFFFFFF, 0x000000 } // identity case
282};
283
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000284static unsigned color_dist16(uint16_t a, uint16_t b) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285 unsigned dr = SkAbs32(SkPacked16ToR32(a) - SkPacked16ToR32(b));
286 unsigned dg = SkAbs32(SkPacked16ToG32(a) - SkPacked16ToG32(b));
287 unsigned db = SkAbs32(SkPacked16ToB32(a) - SkPacked16ToB32(b));
288
289 return SkMax32(dr, SkMax32(dg, db));
290}
291
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000292static unsigned scale_dist(unsigned dist, unsigned scale) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000293 dist >>= 6;
294 dist = (dist << 2) | dist;
295 dist = (dist << 4) | dist;
296 return dist;
297
298// return SkAlphaMul(dist, scale);
299}
300
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000301static void apply_shader(SkPaint* paint, int index) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302 raster_proc proc = gRastProcs[index];
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000303 if (proc) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304 SkPaint p;
305 SkLayerRasterizer* rast = new SkLayerRasterizer;
306
307 p.setAntiAlias(true);
308 proc(rast, p);
309 paint->setRasterizer(rast)->unref();
310 }
311
312#if 1
313 SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
314 paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
315 paint->setColor(SK_ColorBLUE);
316#endif
317}
318
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000319class DemoView : public SampleView {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320public:
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000321 DemoView() {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322
323protected:
324 // overrides from SkEventSink
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000325 virtual bool onQuery(SkEvent* evt) {
326 if (SampleCode::TitleQ(*evt)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000327 SampleCode::TitleR(evt, "Demo");
328 return true;
329 }
330 return this->INHERITED::onQuery(evt);
331 }
332
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000333 virtual bool onClick(Click* click) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000334 return this->INHERITED::onClick(click);
335 }
336
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000337 void makePath(SkPath& path) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338 path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
339 SkPath::kCCW_Direction);
340 for (int index = 0; index < 10; index++) {
341 SkScalar x = SkFloatToScalar(cos(index / 10.0f * 2 * 3.1415925358f));
342 SkScalar y = SkFloatToScalar(sin(index / 10.0f * 2 * 3.1415925358f));
343 x *= index & 1 ? 7 : 14;
344 y *= index & 1 ? 7 : 14;
345 x += SkIntToScalar(20);
346 y += SkIntToScalar(20);
347 if (index == 0)
348 path.moveTo(x, y);
349 else
350 path.lineTo(x, y);
351 }
352 path.close();
353 }
354
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000355 virtual void onDrawContent(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000356 canvas->save();
357 drawPicture(canvas, 0);
358 canvas->restore();
359
360 {
361 SkPicture picture;
362 SkCanvas* record = picture.beginRecording(320, 480);
363 drawPicture(record, 120);
364 canvas->translate(0, SkIntToScalar(120));
365
366 SkRect clip;
367 clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
368 do {
369 canvas->save();
370 canvas->clipRect(clip);
371 picture.draw(canvas);
372 canvas->restore();
373 if (clip.fRight < SkIntToScalar(320))
374 clip.offset(SkIntToScalar(160), 0);
375 else if (clip.fBottom < SkIntToScalar(480))
376 clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
377 else
378 break;
379 } while (true);
380 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381 }
382
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000383 void drawPicture(SkCanvas* canvas, int spriteOffset) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000384 SkMatrix matrix; matrix.reset();
385 SkPaint paint;
386 SkPath path;
387 SkPoint start = {0, 0};
388 SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
389 SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
390 SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
391 SkScalar left = 0, top = 0, x = 0, y = 0;
reed@google.com261b8e22011-04-14 17:53:24 +0000392 size_t index;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000393
394 char ascii[] = "ascii...";
395 size_t asciiLength = sizeof(ascii) - 1;
396 char utf8[] = "utf8" "\xe2\x80\xa6";
397 short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
398 short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
399
400 makePath(path);
401 SkTDArray<SkPoint>(pos);
402 pos.setCount(asciiLength);
403 for (index = 0; index < asciiLength; index++)
404 pos[index].set(SkIntToScalar(index * 10), SkIntToScalar(index * 2));
405 SkTDArray<SkPoint>(pos2);
406 pos2.setCount(asciiLength);
407 for (index = 0; index < asciiLength; index++)
408 pos2[index].set(SkIntToScalar(index * 10), SkIntToScalar(20));
409
410 // shaders
411 SkPoint linearPoints[] = { 0, 0, SkIntToScalar(40), SkIntToScalar(40) };
412 SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
413 SkScalar* linearPos = NULL;
414 int linearCount = 2;
415 SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
416 SkUnitMapper* linearMapper = new SkDiscreteMapper(3);
417 SkAutoUnref unmapLinearMapper(linearMapper);
418 SkShader* linear = SkGradientShader::CreateLinear(linearPoints,
419 linearColors, linearPos, linearCount, linearMode, linearMapper);
420
421 SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
422 SkScalar radialRadius = SkIntToScalar(25);
423 SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
424 SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
425 int radialCount = 3;
426 SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
427 SkUnitMapper* radialMapper = new SkCosineMapper();
428 SkAutoUnref unmapRadialMapper(radialMapper);
429 SkShader* radial = SkGradientShader::CreateRadial(radialCenter,
430 radialRadius, radialColors, radialPos, radialCount,
431 radialMode, radialMapper);
432
433 SkTransparentShader* transparentShader = new SkTransparentShader();
434 SkEmbossMaskFilter::Light light;
435 light.fDirection[0] = SK_Scalar1/2;
436 light.fDirection[1] = SK_Scalar1/2;
437 light.fDirection[2] = SK_Scalar1/3;
438 light.fAmbient = 0x48;
439 light.fSpecular = 0x80;
440 SkScalar radius = SkIntToScalar(12)/5;
441 SkEmbossMaskFilter* embossFilter = new SkEmbossMaskFilter(light,
442 radius);
443
reed@android.com048522d2009-06-23 12:19:41 +0000444 SkXfermode* xfermode = SkXfermode::Create(SkXfermode::kXor_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000445 SkColorFilter* lightingFilter = SkColorFilter::CreateLightingFilter(
446 0xff89bc45, 0xff112233);
447
448 canvas->save();
449 canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
450 paint.setFlags(SkPaint::kAntiAlias_Flag | SkPaint::kFilterBitmap_Flag);
451 // !!! draw through a clip
452 paint.setColor(SK_ColorLTGRAY);
453 paint.setStyle(SkPaint::kFill_Style);
454 SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
455 canvas->clipRect(clip);
456 paint.setShader(SkShader::CreateBitmapShader(fTx,
457 SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode))->unref();
458 canvas->drawPaint(paint);
459 canvas->save();
460
461 // line (exercises xfermode, colorShader, colorFilter, filterShader)
462 paint.setColor(SK_ColorGREEN);
463 paint.setStrokeWidth(SkIntToScalar(10));
464 paint.setStyle(SkPaint::kStroke_Style);
465 paint.setXfermode(xfermode)->unref();
466 paint.setColorFilter(lightingFilter)->unref();
467 canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
468 paint.setXfermode(NULL);
469 paint.setColorFilter(NULL);
470
471 // rectangle
472 paint.setStyle(SkPaint::kFill_Style);
473 canvas->translate(SkIntToScalar(50), 0);
474 paint.setColor(SK_ColorYELLOW);
475 paint.setShader(linear)->unref();
476 paint.setPathEffect(pathEffectTest())->unref();
477 canvas->drawRect(rect, paint);
478 paint.setPathEffect(NULL);
479
480 // circle w/ emboss & transparent (exercises 3dshader)
481 canvas->translate(SkIntToScalar(50), 0);
482 paint.setMaskFilter(embossFilter)->unref();
483 canvas->drawOval(rect, paint);
484 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
485 paint.setShader(transparentShader)->unref();
486 canvas->drawOval(rect, paint);
487 canvas->translate(0, SkIntToScalar(-10));
488
489 // path
490 canvas->translate(SkIntToScalar(50), 0);
491 paint.setColor(SK_ColorRED);
492 paint.setStyle(SkPaint::kStroke_Style);
493 paint.setStrokeWidth(SkIntToScalar(5));
494 paint.setShader(radial)->unref();
495 paint.setMaskFilter(NULL);
496 canvas->drawPath(path, paint);
497
498 paint.setShader(NULL);
499 // bitmap, sprite
500 canvas->translate(SkIntToScalar(50), 0);
501 paint.setStyle(SkPaint::kFill_Style);
502 canvas->drawBitmap(fBug, left, top, &paint);
503 canvas->translate(SkIntToScalar(30), 0);
504 canvas->drawSprite(fTb,
505 SkScalarRound(canvas->getTotalMatrix().getTranslateX()),
506 spriteOffset + 10, &paint);
507
508 canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
509 paint.setShader(shaderTest())->unref(); // test compose shader
510 canvas->drawRect(rect2, paint);
511 paint.setShader(NULL);
512
513 canvas->restore();
514 // text
515 canvas->translate(0, SkIntToScalar(60));
516 canvas->save();
517 paint.setColor(SK_ColorGRAY);
518 canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
519 canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
520
521 canvas->translate(SkIntToScalar(50), 0);
522 paint.setColor(SK_ColorCYAN);
523 canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
524
525 canvas->translate(SkIntToScalar(30), 0);
526 paint.setColor(SK_ColorMAGENTA);
527 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
528 matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
529 canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
530 canvas->translate(0, SkIntToScalar(20));
531 canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
532 canvas->restore();
533
534 canvas->translate(0, SkIntToScalar(60));
535 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
536 canvas->restore();
537 }
538
539 /*
540./SkColorFilter.h:25:class SkColorFilter : public SkFlattenable { -- abstract
541 static SkColorFilter* CreatXfermodeFilter() *** untested ***
542 static SkColorFilter* CreatePorterDuffFilter() *** untested ***
543 static SkColorFilter* CreateLightingFilter() -- tested
544./SkDrawLooper.h:9:class SkDrawLooper : public SkFlattenable { -- virtually abstract
545 ./SkBlurDrawLooper.h:9:class SkBlurDrawLooper : public SkDrawLooper { *** untested ***
546./SkMaskFilter.h:41:class SkMaskFilter : public SkFlattenable { -- abstract chmod +w .h
547 ./SkEmbossMaskFilter.h:27:class SkEmbossMaskFilter : public SkMaskFilter { -- tested
548./SkPathEffect.h:33:class SkPathEffect : public SkFlattenable { -- abstract
549 ./Sk1DPathEffect.h:27:class Sk1DPathEffect : public SkPathEffect { -- abstract
550 ./Sk1DPathEffect.h:48:class SkPath1DPathEffect : public Sk1DPathEffect { -- tested
551 ./Sk2DPathEffect.h:25:class Sk2DPathEffect : public SkPathEffect { *** untested ***
552 ./SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect { *** untested ***
553 ./SkDashPathEffect.h:27:class SkDashPathEffect : public SkPathEffect {
554 ./SkDiscretePathEffect.h:27:class SkDiscretePathEffect : public SkPathEffect {
555 ./SkPaint.h:760:class SkStrokePathEffect : public SkPathEffect {
556 ./SkPathEffect.h:58:class SkPairPathEffect : public SkPathEffect {
557 ./SkPathEffect.h:78:class SkComposePathEffect : public SkPairPathEffect {
558 ./SkPathEffect.h:114:class SkSumPathEffect : public SkPairPathEffect {
559./SkRasterizer.h:29:class SkRasterizer : public SkFlattenable {
560 ./SkLayerRasterizer.h:27:class SkLayerRasterizer : public SkRasterizer {
561./SkShader.h:36:class SkShader : public SkFlattenable {
562 ./SkColorFilter.h:59:class SkFilterShader : public SkShader {
563 ./SkColorShader.h:26:class SkColorShader : public SkShader {
564 ./SkShaderExtras.h:31:class SkComposeShader : public SkShader {
565 ./SkTransparentShader.h:23:class SkTransparentShader : public SkShader {
566./SkUnitMapper.h:24:class SkUnitMapper : public SkFlattenable {
567 ./SkUnitMapper.h:33:class SkDiscreteMapper : public SkUnitMapper {
568 ./SkUnitMapper.h:51:class SkFlipCosineMapper : public SkUnitMapper {
569./SkXfermode.h:32:class SkXfermode : public SkFlattenable {
570 ./SkAvoidXfermode.h:28:class SkAvoidXfermode : public SkXfermode { *** not done *** chmod +w .h .cpp
571 ./SkXfermode.h:54:class SkProcXfermode : public SkXfermode {
572 */
573
574 /*
575./SkBlurMaskFilter.h:25:class SkBlurMaskFilter {
576 chmod +w SkBlurMaskFilter.cpp
577./SkGradientShader.h:30:class SkGradientShader {
578 */
579 // save layer, bounder, looper
580 // matrix
581 // clip /path/region
582 // bitmap proc shader ?
583
584/* untested:
585SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect {
586*/
587
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000588 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000589 fClickPt.set(x, y);
590 this->inval(NULL);
591 return this->INHERITED::onFindClickHandler(x, y);
592 }
593
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000594 SkPathEffect* pathEffectTest() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000595 static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
596 SkScalar gPhase = 0;
597 SkPath path;
598 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
599 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
600 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
601 path.close();
602 path.offset(SkIntToScalar(-6), 0);
603 SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12),
604 gPhase, SkPath1DPathEffect::kRotate_Style);
605 SkPathEffect* inner = new SkDiscretePathEffect(SkIntToScalar(2),
606 SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
607 SkPathEffect* result = new SkComposePathEffect(outer, inner);
608 outer->unref();
609 inner->unref();
610 return result;
611 }
612
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000613 SkPathEffect* pathEffectTest2() { // unsure this works (has no visible effect)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000614 SkPathEffect* outer = new SkStrokePathEffect(SkIntToScalar(4),
615 SkPaint::kStroke_Style, SkPaint::kMiter_Join, SkPaint::kButt_Cap);
616 static const SkScalar intervals[] = {SkIntToScalar(1), SkIntToScalar(2),
617 SkIntToScalar(2), SkIntToScalar(1)};
618 SkPathEffect* inner = new SkDashPathEffect(intervals,
619 sizeof(intervals) / sizeof(intervals[0]), 0);
620 SkPathEffect* result = new SkSumPathEffect(outer, inner);
621 outer->unref();
622 inner->unref();
623 return result;
624 }
625
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000626 SkShader* shaderTest() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000627 SkPoint pts[] = {0, 0, SkIntToScalar(100), 0 };
628 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
629 SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL,
630 2, SkShader::kClamp_TileMode);
631 pts[1].set(0, SkIntToScalar(100));
632 SkColor colors2[] = {SK_ColorBLACK, SkColorSetARGB(0x80, 0, 0, 0)};
633 SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors2, NULL,
634 2, SkShader::kClamp_TileMode);
reed@android.com048522d2009-06-23 12:19:41 +0000635 SkXfermode* mode = SkXfermode::Create(SkXfermode::kDstIn_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000636 SkShader* result = new SkComposeShader(shaderA, shaderB, mode);
637 shaderA->unref();
638 shaderB->unref();
639 mode->unref();
640 return result;
641 }
642
643 virtual void startTest() {
644 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
645 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
646 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/05psp04.gif", &fTx);
647 }
648
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000649 void drawRaster(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000650 for (int index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
651 drawOneRaster(canvas);
652 }
653
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000654 void drawOneRaster(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000655 canvas->save();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000656
657 SkScalar x = SkIntToScalar(20);
658 SkScalar y = SkIntToScalar(40);
659 SkPaint paint;
660
661 paint.setAntiAlias(true);
662 paint.setTextSize(SkIntToScalar(48));
reed@android.comaa5a7db2009-05-27 01:20:10 +0000663 paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
664 SkTypeface::kBold));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000665
666 SkString str("GOOGLE");
667
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000668 for (int i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000669 apply_shader(&paint, i);
670
671 // paint.setMaskFilter(NULL);
672 // paint.setColor(SK_ColorBLACK);
673
674#if 01
675 int index = i % SK_ARRAY_COUNT(gLightingColors);
676 paint.setColorFilter(SkColorFilter::CreateLightingFilter(
677 gLightingColors[index].fMul,
678 gLightingColors[index].fAdd))->unref();
679#endif
680
681 canvas->drawText(str.c_str(), str.size(), x, y, paint);
682 SkRect oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
683 paint.setStyle(SkPaint::kStroke_Style);
684 canvas->drawOval(oval, paint);
685 paint.setStyle(SkPaint::kFill_Style);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000686
687 y += paint.getFontSpacing();
688 }
689
690 canvas->restore();
691
reed@android.com6b82d1a2009-06-03 02:35:01 +0000692 if (1) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000693 SkAvoidXfermode mode(SK_ColorWHITE, 0xFF,
694 SkAvoidXfermode::kTargetColor_Mode);
695 SkPaint paint;
696 x += SkIntToScalar(20);
697 SkRect r = { x, 0, x + SkIntToScalar(360), SkIntToScalar(700) };
698 paint.setXfermode(&mode);
699 paint.setColor(SK_ColorGREEN);
700 paint.setAntiAlias(true);
701 canvas->drawOval(r, paint);
702 }
703 }
704
705private:
706 SkPoint fClickPt;
707 SkBitmap fBug, fTb, fTx;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000708 typedef SampleView INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000709};
710
711//////////////////////////////////////////////////////////////////////////////
712
713static SkView* MyFactory() { return new DemoView; }
714static SkViewRegister reg(MyFactory);
715