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