• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "SampleCode.h"
8 #include "SkBlurMask.h"
9 #include "SkCanvas.h"
10 #include "SkView.h"
11 #include "Sk1DPathEffect.h"
12 #include "Sk2DPathEffect.h"
13 #include "SkBlurMaskFilter.h"
14 #include "SkColorMatrixFilter.h"
15 #include "SkColorPriv.h"
16 #include "SkCornerPathEffect.h"
17 #include "SkDashPathEffect.h"
18 #include "SkDiscretePathEffect.h"
19 #include "SkEmbossMaskFilter.h"
20 #include "SkReadBuffer.h"
21 #include "SkWriteBuffer.h"
22 #include "SkGradientShader.h"
23 #include "SkLayerRasterizer.h"
24 #include "SkMath.h"
25 #include "SkPath.h"
26 #include "SkPictureRecorder.h"
27 #include "SkRegion.h"
28 #include "SkShader.h"
29 #include "SkCornerPathEffect.h"
30 #include "SkPathMeasure.h"
31 #include "SkPicture.h"
32 #include "SkRandom.h"
33 #include "SkTypeface.h"
34 #include "SkUtils.h"
35 
36 #include <math.h>
37 #include "DecodeFile.h"
38 
r0(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)39 static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
40     p.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
41                                            SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)),
42                                            SkBlurMaskFilter::kNone_BlurFlag));
43     rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
44 
45     p.setMaskFilter(nullptr);
46     p.setStyle(SkPaint::kStroke_Style);
47     p.setStrokeWidth(SK_Scalar1);
48     rastBuilder->addLayer(p);
49 
50     p.setAlpha(0x11);
51     p.setStyle(SkPaint::kFill_Style);
52     p.setBlendMode(SkBlendMode::kSrc);
53     rastBuilder->addLayer(p);
54 }
55 
r1(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)56 static void r1(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
57     rastBuilder->addLayer(p);
58 
59     p.setAlpha(0x40);
60     p.setBlendMode(SkBlendMode::kSrc);
61     p.setStyle(SkPaint::kStroke_Style);
62     p.setStrokeWidth(SK_Scalar1*2);
63     rastBuilder->addLayer(p);
64 }
65 
r2(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)66 static void r2(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
67     p.setStyle(SkPaint::kStrokeAndFill_Style);
68     p.setStrokeWidth(SK_Scalar1*4);
69     rastBuilder->addLayer(p);
70 
71     p.setStyle(SkPaint::kStroke_Style);
72     p.setStrokeWidth(SK_Scalar1*3/2);
73     p.setBlendMode(SkBlendMode::kClear);
74     rastBuilder->addLayer(p);
75 }
76 
r3(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)77 static void r3(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
78     p.setStyle(SkPaint::kStroke_Style);
79     p.setStrokeWidth(SK_Scalar1*3);
80     rastBuilder->addLayer(p);
81 
82     p.setAlpha(0x20);
83     p.setStyle(SkPaint::kFill_Style);
84     p.setBlendMode(SkBlendMode::kSrc);
85     rastBuilder->addLayer(p);
86 }
87 
r4(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)88 static void r4(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
89     p.setAlpha(0x60);
90     rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
91 
92     p.setAlpha(0xFF);
93     p.setBlendMode(SkBlendMode::kClear);
94     rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
95 
96     p.setBlendMode(SkBlendMode::kSrcOver);
97     rastBuilder->addLayer(p);
98 }
99 
r5(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)100 static void r5(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
101     rastBuilder->addLayer(p);
102 
103     p.setPathEffect(SkDiscretePathEffect::Make(SK_Scalar1*4, SK_Scalar1*3));
104     p.setBlendMode(SkBlendMode::kSrcOut);
105     rastBuilder->addLayer(p);
106 }
107 
r6(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)108 static void r6(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
109     rastBuilder->addLayer(p);
110 
111     p.setAntiAlias(false);
112     SkLayerRasterizer::Builder rastBuilder2;
113     r5(&rastBuilder2, p);
114     p.setRasterizer(rastBuilder2.detach());
115     p.setBlendMode(SkBlendMode::kClear);
116     rastBuilder->addLayer(p);
117 }
118 
119 class Dot2DPathEffect : public Sk2DPathEffect {
120 public:
Dot2DPathEffect(SkScalar radius,const SkMatrix & matrix)121     Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
122         : Sk2DPathEffect(matrix), fRadius(radius) {}
123 
124     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect)
125 
126 protected:
next(const SkPoint & loc,int u,int v,SkPath * dst) const127     void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
128         dst->addCircle(loc.fX, loc.fY, fRadius);
129     }
130 
flatten(SkWriteBuffer & buffer) const131     void flatten(SkWriteBuffer& buffer) const override {
132         this->INHERITED::flatten(buffer);
133         buffer.writeScalar(fRadius);
134     }
135 
136 private:
137     SkScalar fRadius;
138 
139     typedef Sk2DPathEffect INHERITED;
140 };
141 
r7(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)142 static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
143     SkMatrix    lattice;
144     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
145     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
146     p.setPathEffect(sk_make_sp<Dot2DPathEffect>(SK_Scalar1*4, lattice));
147     rastBuilder->addLayer(p);
148 }
149 
r8(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)150 static void r8(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
151     rastBuilder->addLayer(p);
152 
153     SkMatrix    lattice;
154     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
155     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
156     p.setPathEffect(sk_make_sp<Dot2DPathEffect>(SK_Scalar1*2, lattice));
157     p.setBlendMode(SkBlendMode::kClear);
158     rastBuilder->addLayer(p);
159 
160     p.setPathEffect(nullptr);
161     p.setBlendMode(SkBlendMode::kSrcOver);
162     p.setStyle(SkPaint::kStroke_Style);
163     p.setStrokeWidth(SK_Scalar1);
164     rastBuilder->addLayer(p);
165 }
166 
r9(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)167 static void r9(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
168     rastBuilder->addLayer(p);
169 
170     SkMatrix    lattice;
171     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
172     lattice.postRotate(SkIntToScalar(30), 0, 0);
173     p.setPathEffect(SkLine2DPathEffect::Make(SK_Scalar1*2, lattice));
174     p.setBlendMode(SkBlendMode::kClear);
175     rastBuilder->addLayer(p);
176 
177     p.setPathEffect(nullptr);
178     p.setBlendMode(SkBlendMode::kSrcOver);
179     p.setStyle(SkPaint::kStroke_Style);
180     p.setStrokeWidth(SK_Scalar1);
181     rastBuilder->addLayer(p);
182 }
183 
184 typedef void (*raster_proc)(SkLayerRasterizer::Builder*, SkPaint&);
185 
186 static const raster_proc gRastProcs[] = {
187     r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
188 };
189 
190 static const struct {
191     SkColor fMul, fAdd;
192 } gLightingColors[] = {
193     { 0x808080, 0x800000 }, // general case
194     { 0x707070, 0x707070 }, // no-pin case
195     { 0xFFFFFF, 0x800000 }, // just-add case
196     { 0x808080, 0x000000 }, // just-mul case
197     { 0xFFFFFF, 0x000000 }  // identity case
198 };
199 
apply_shader(SkPaint * paint,int index)200 static void apply_shader(SkPaint* paint, int index) {
201     raster_proc proc = gRastProcs[index];
202     if (proc) {
203         SkPaint p;
204         SkLayerRasterizer::Builder rastBuilder;
205 
206         p.setAntiAlias(true);
207         proc(&rastBuilder, p);
208         paint->setRasterizer(rastBuilder.detach());
209     }
210 
211 #ifdef SK_SUPPORT_LEGACY_EMBOSSMASKFILTER
212     SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
213     paint->setMaskFilter(SkBlurMaskFilter::MakeEmboss(
214                 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)), dir,
215                 SK_Scalar1/4, SkIntToScalar(4)));
216     paint->setColor(SK_ColorBLUE);
217 #endif
218 }
219 
220 class DemoView : public SampleView {
221 public:
DemoView()222     DemoView() {}
223 
224 protected:
225     // overrides from SkEventSink
onQuery(SkEvent * evt)226     virtual bool onQuery(SkEvent* evt) {
227         if (SampleCode::TitleQ(*evt)) {
228             SampleCode::TitleR(evt, "Demo");
229             return true;
230         }
231         return this->INHERITED::onQuery(evt);
232     }
233 
onClick(Click * click)234     virtual bool onClick(Click* click) {
235         return this->INHERITED::onClick(click);
236     }
237 
makePath(SkPath & path)238     void makePath(SkPath& path) {
239         path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
240             SkPath::kCCW_Direction);
241         for (int index = 0; index < 10; index++) {
242             SkScalar x = (float) cos(index / 10.0f * 2 * 3.1415925358f);
243             SkScalar y = (float) sin(index / 10.0f * 2 * 3.1415925358f);
244             x *= index & 1 ? 7 : 14;
245             y *= index & 1 ? 7 : 14;
246             x += SkIntToScalar(20);
247             y += SkIntToScalar(20);
248             if (index == 0)
249                 path.moveTo(x, y);
250             else
251                 path.lineTo(x, y);
252         }
253         path.close();
254     }
255 
onDrawContent(SkCanvas * canvas)256     virtual void onDrawContent(SkCanvas* canvas) {
257         canvas->save();
258         this->drawPicture(canvas, 0);
259         canvas->restore();
260 
261         {
262             SkPictureRecorder recorder;
263             {
264                 SkCanvas* record = recorder.beginRecording(320, 480, nullptr, 0);
265                 this->drawPicture(record, 120);
266             }
267             sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
268 
269             canvas->translate(0, SkIntToScalar(120));
270 
271             SkRect clip;
272             clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
273             do {
274                 canvas->save();
275                 canvas->clipRect(clip);
276                 picture->playback(canvas);
277                 canvas->restore();
278                 if (clip.fRight < SkIntToScalar(320))
279                     clip.offset(SkIntToScalar(160), 0);
280                 else if (clip.fBottom < SkIntToScalar(480))
281                     clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
282                 else
283                     break;
284             } while (true);
285         }
286     }
287 
drawPicture(SkCanvas * canvas,int spriteOffset)288     void drawPicture(SkCanvas* canvas, int spriteOffset) {
289         SkMatrix matrix; matrix.reset();
290         SkPaint paint;
291         SkPath path;
292         SkPoint start = {0, 0};
293         SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
294         SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
295         SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
296         SkScalar left = 0, top = 0, x = 0, y = 0;
297         int index;
298 
299         char ascii[] = "ascii...";
300         int asciiLength = sizeof(ascii) - 1;
301         char utf8[] = "utf8" "\xe2\x80\xa6";
302         short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
303         short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
304 
305         makePath(path);
306         SkTDArray<SkPoint>(pos);
307         pos.setCount(asciiLength);
308         for (index = 0;  index < asciiLength; index++)
309             pos[index].set(SkIntToScalar((unsigned int)index * 10),
310                                        SkIntToScalar((unsigned int)index * 2));
311         SkTDArray<SkPoint>(pos2);
312         pos2.setCount(asciiLength);
313         for (index = 0;  index < asciiLength; index++)
314             pos2[index].set(SkIntToScalar((unsigned int)index * 10),
315                                         SkIntToScalar(20));
316 
317         // shaders
318         SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } };
319         SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
320         SkScalar* linearPos = nullptr;
321         int linearCount = 2;
322         SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
323         auto linear = SkGradientShader::MakeLinear(linearPoints,
324             linearColors, linearPos, linearCount, linearMode);
325 
326         SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
327         SkScalar radialRadius = SkIntToScalar(25);
328         SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
329         SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
330         int radialCount = 3;
331         SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
332         auto radial = SkGradientShader::MakeRadial(radialCenter,
333             radialRadius, radialColors, radialPos, radialCount,
334             radialMode);
335 
336         SkEmbossMaskFilter::Light light;
337         light.fDirection[0] = SK_Scalar1/2;
338         light.fDirection[1] = SK_Scalar1/2;
339         light.fDirection[2] = SK_Scalar1/3;
340         light.fAmbient        = 0x48;
341         light.fSpecular        = 0x80;
342 
343         auto lightingFilter = SkColorMatrixFilter::MakeLightingFilter(
344             0xff89bc45, 0xff112233);
345 
346         canvas->save();
347         canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
348         paint.setAntiAlias(true);
349         paint.setFilterQuality(kLow_SkFilterQuality);
350         // !!! draw through a clip
351         paint.setColor(SK_ColorLTGRAY);
352         paint.setStyle(SkPaint::kFill_Style);
353         SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
354         canvas->clipRect(clip);
355         paint.setShader(SkShader::MakeBitmapShader(fTx,
356             SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode));
357         canvas->drawPaint(paint);
358         canvas->save();
359 
360         // line (exercises xfermode, colorShader, colorFilter, filterShader)
361         paint.setColor(SK_ColorGREEN);
362         paint.setStrokeWidth(SkIntToScalar(10));
363         paint.setStyle(SkPaint::kStroke_Style);
364         paint.setBlendMode(SkBlendMode::kXor);
365         paint.setColorFilter(lightingFilter);
366         canvas->drawLine(start, stop, paint); // should not be green
367         paint.setBlendMode(SkBlendMode::kSrcOver);
368         paint.setColorFilter(nullptr);
369 
370         // rectangle
371         paint.setStyle(SkPaint::kFill_Style);
372         canvas->translate(SkIntToScalar(50), 0);
373         paint.setColor(SK_ColorYELLOW);
374         paint.setShader(linear);
375         paint.setPathEffect(pathEffectTest());
376         canvas->drawRect(rect, paint);
377         paint.setPathEffect(nullptr);
378 
379         // circle w/ emboss & transparent (exercises 3dshader)
380         canvas->translate(SkIntToScalar(50), 0);
381         paint.setMaskFilter(SkEmbossMaskFilter::Make(
382                                      SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(12)/5), light));
383         canvas->drawOval(rect, paint);
384         canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
385 //        paint.setShader(transparentShader)->unref();
386         canvas->drawOval(rect, paint);
387         canvas->translate(0, SkIntToScalar(-10));
388 
389         // path
390         canvas->translate(SkIntToScalar(50), 0);
391         paint.setColor(SK_ColorRED);
392         paint.setStyle(SkPaint::kStroke_Style);
393         paint.setStrokeWidth(SkIntToScalar(5));
394         paint.setShader(radial);
395         paint.setMaskFilter(nullptr);
396         canvas->drawPath(path, paint);
397 
398         paint.setShader(nullptr);
399         // bitmap
400         canvas->translate(SkIntToScalar(50), 0);
401         paint.setStyle(SkPaint::kFill_Style);
402         canvas->drawBitmap(fBug, left, top, &paint);
403 
404         canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
405         paint.setShader(shaderTest()); // test compose shader
406         canvas->drawRect(rect2, paint);
407         paint.setShader(nullptr);
408 
409         canvas->restore();
410         // text
411         canvas->translate(0, SkIntToScalar(60));
412         canvas->save();
413         paint.setColor(SK_ColorGRAY);
414         canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
415         canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
416 
417         canvas->translate(SkIntToScalar(50), 0);
418         paint.setColor(SK_ColorCYAN);
419         canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
420 
421         canvas->translate(SkIntToScalar(30), 0);
422         paint.setColor(SK_ColorMAGENTA);
423         paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
424         matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
425         canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
426         canvas->translate(0, SkIntToScalar(20));
427         canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
428         canvas->restore();
429 
430         canvas->translate(0, SkIntToScalar(60));
431         paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
432         canvas->restore();
433     }
434 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)435     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
436         fClickPt.set(x, y);
437         this->inval(nullptr);
438         return this->INHERITED::onFindClickHandler(x, y, modi);
439     }
440 
pathEffectTest()441     sk_sp<SkPathEffect> pathEffectTest() {
442         static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
443         SkScalar gPhase = 0;
444         SkPath path;
445         path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
446         for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
447             path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
448         path.close();
449         path.offset(SkIntToScalar(-6), 0);
450         auto outer = SkPath1DPathEffect::Make(path, SkIntToScalar(12),
451             gPhase, SkPath1DPathEffect::kRotate_Style);
452         auto inner = SkDiscretePathEffect::Make(SkIntToScalar(2),
453             SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
454         return SkPathEffect::MakeCompose(outer, inner);
455     }
456 
shaderTest()457     sk_sp<SkShader> shaderTest() {
458         SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } };
459         SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
460         auto shaderA = SkGradientShader::MakeLinear(pts, colors, nullptr,
461             2, SkShader::kClamp_TileMode);
462         pts[1].set(0, SkIntToScalar(100));
463         SkColor colors2[] = {SK_ColorBLACK,  SkColorSetARGB(0x80, 0, 0, 0)};
464         auto shaderB = SkGradientShader::MakeLinear(pts, colors2, nullptr,
465             2, SkShader::kClamp_TileMode);
466         return SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB),
467                                            SkBlendMode::kDstIn);
468     }
469 
startTest()470     virtual void startTest() {
471         decode_file("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
472         decode_file("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
473         decode_file("/Users/caryclark/Desktop/05psp04.gif", &fTx);
474     }
475 
drawRaster(SkCanvas * canvas)476     void drawRaster(SkCanvas* canvas)  {
477         for (size_t index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
478             drawOneRaster(canvas);
479     }
480 
drawOneRaster(SkCanvas * canvas)481     void drawOneRaster(SkCanvas* canvas) {
482         canvas->save();
483 
484         SkScalar    x = SkIntToScalar(20);
485         SkScalar    y = SkIntToScalar(40);
486         SkPaint     paint;
487 
488         paint.setAntiAlias(true);
489         paint.setTextSize(SkIntToScalar(48));
490         paint.setTypeface(SkTypeface::MakeFromName("sans-serif",
491                                                    SkFontStyle::FromOldStyle(SkTypeface::kBold)));
492 
493         SkString str("GOOGLE");
494 
495         for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
496             apply_shader(&paint, (int)i);
497 
498           //  paint.setMaskFilter(nullptr);
499           //  paint.setColor(SK_ColorBLACK);
500 
501 #if 01
502             int index = i % SK_ARRAY_COUNT(gLightingColors);
503             paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(
504                                     gLightingColors[index].fMul,
505                                     gLightingColors[index].fAdd));
506 #endif
507 
508             canvas->drawString(str, x, y, paint);
509             SkRect  oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
510             paint.setStyle(SkPaint::kStroke_Style);
511             canvas->drawOval(oval, paint);
512             paint.setStyle(SkPaint::kFill_Style);
513 
514             y += paint.getFontSpacing();
515         }
516 
517         canvas->restore();
518     }
519 
520 private:
521     SkPoint fClickPt;
522     SkBitmap fBug, fTb, fTx;
523     typedef SampleView INHERITED;
524 };
525 
526 //////////////////////////////////////////////////////////////////////////////
527 
MyFactory()528 static SkView* MyFactory() { return new DemoView; }
529 static SkViewRegister reg(MyFactory);
530