| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "sk_tool_utils.h" | 8 #include "sk_tool_utils.h" |
| 9 #include "SampleCode.h" | 9 #include "SampleCode.h" |
| 10 #include "SkView.h" | 10 #include "SkView.h" |
| 11 #include "SkCanvas.h" | 11 #include "SkCanvas.h" |
| 12 #include "SkGeometry.h" |
| 12 #include "SkPathMeasure.h" | 13 #include "SkPathMeasure.h" |
| 13 #include "SkRandom.h" | 14 #include "SkRandom.h" |
| 14 #include "SkRRect.h" | 15 #include "SkRRect.h" |
| 15 #include "SkColorPriv.h" | 16 #include "SkColorPriv.h" |
| 16 #include "SkStrokerPriv.h" | 17 #include "SkStrokerPriv.h" |
| 17 #include "SkSurface.h" | 18 #include "SkSurface.h" |
| 18 | 19 |
| 19 static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) { | 20 static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) { |
| 20 const SkScalar TOL = 7; | 21 const SkScalar TOL = 7; |
| 21 return SkPoint::Distance(target, SkPoint::Make(x, y)) <= TOL; | 22 return SkPoint::Distance(target, SkPoint::Make(x, y)) <= TOL; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 StrokeTypeButton fTextButton; | 116 StrokeTypeButton fTextButton; |
| 116 SkString fText; | 117 SkString fText; |
| 117 SkScalar fTextSize; | 118 SkScalar fTextSize; |
| 118 SkScalar fWeight; | 119 SkScalar fWeight; |
| 119 SkScalar fWidth, fDWidth; | 120 SkScalar fWidth, fDWidth; |
| 120 SkScalar fWidthScale; | 121 SkScalar fWidthScale; |
| 121 int fW, fH, fZoom; | 122 int fW, fH, fZoom; |
| 122 bool fAnimate; | 123 bool fAnimate; |
| 123 bool fDrawRibs; | 124 bool fDrawRibs; |
| 124 bool fDrawTangents; | 125 bool fDrawTangents; |
| 126 bool fDrawTDivs; |
| 125 #ifdef SK_DEBUG | 127 #ifdef SK_DEBUG |
| 126 #define kStrokerErrorMin 0.001f | 128 #define kStrokerErrorMin 0.001f |
| 127 #define kStrokerErrorMax 5 | 129 #define kStrokerErrorMax 5 |
| 128 #endif | 130 #endif |
| 129 #define kWidthMin 1 | 131 #define kWidthMin 1 |
| 130 #define kWidthMax 100 | 132 #define kWidthMax 100 |
| 131 public: | 133 public: |
| 132 QuadStrokerView() { | 134 QuadStrokerView() { |
| 133 this->setBGColor(SK_ColorLTGRAY); | 135 this->setBGColor(SK_ColorLTGRAY); |
| 134 | 136 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 } | 283 } |
| 282 | 284 |
| 283 void draw_ribs(SkCanvas* canvas, const SkPath& path, SkScalar width, | 285 void draw_ribs(SkCanvas* canvas, const SkPath& path, SkScalar width, |
| 284 SkColor color) { | 286 SkColor color) { |
| 285 const SkScalar radius = width / 2; | 287 const SkScalar radius = width / 2; |
| 286 | 288 |
| 287 SkPathMeasure meas(path, false); | 289 SkPathMeasure meas(path, false); |
| 288 SkScalar total = meas.getLength(); | 290 SkScalar total = meas.getLength(); |
| 289 | 291 |
| 290 SkScalar delta = 8; | 292 SkScalar delta = 8; |
| 291 SkPaint paint; | 293 SkPaint paint, labelP; |
| 292 paint.setColor(color); | 294 paint.setColor(color); |
| 293 | 295 labelP.setColor(color & 0xff5f9f5f); |
| 294 SkPoint pos, tan; | 296 SkPoint pos, tan; |
| 297 int index = 0; |
| 295 for (SkScalar dist = 0; dist <= total; dist += delta) { | 298 for (SkScalar dist = 0; dist <= total; dist += delta) { |
| 296 if (meas.getPosTan(dist, &pos, &tan)) { | 299 if (meas.getPosTan(dist, &pos, &tan)) { |
| 297 tan.scale(radius); | 300 tan.scale(radius); |
| 298 tan.rotateCCW(); | 301 tan.rotateCCW(); |
| 299 canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(), | 302 canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(), |
| 300 pos.x() - tan.x(), pos.y() - tan.y(), paint); | 303 pos.x() - tan.x(), pos.y() - tan.y(), paint); |
| 304 if (0 == index % 10) { |
| 305 SkString label; |
| 306 label.appendS32(index); |
| 307 SkRect dot = SkRect::MakeXYWH(pos.x() - 2, pos.y() - 2, 4, 4
); |
| 308 canvas->drawRect(dot, labelP); |
| 309 canvas->drawText(label.c_str(), label.size(), |
| 310 pos.x() - tan.x() * 1.25f, pos.y() - tan.y() * 1.25f, la
belP); |
| 311 } |
| 312 } |
| 313 ++index; |
| 314 } |
| 315 } |
| 316 |
| 317 void draw_t_divs(SkCanvas* canvas, const SkPath& path, SkScalar width, SkCol
or color) { |
| 318 const SkScalar radius = width / 2; |
| 319 SkPaint paint; |
| 320 paint.setColor(color); |
| 321 SkPathMeasure meas(path, false); |
| 322 SkScalar total = meas.getLength(); |
| 323 SkScalar delta = 8; |
| 324 int ribs = 0; |
| 325 for (SkScalar dist = 0; dist <= total; dist += delta) { |
| 326 ++ribs; |
| 327 } |
| 328 SkPath::RawIter iter(path); |
| 329 SkPoint pts[4]; |
| 330 if (SkPath::kMove_Verb != iter.next(pts)) { |
| 331 SkASSERT(0); |
| 332 return; |
| 333 } |
| 334 SkPath::Verb verb = iter.next(pts); |
| 335 SkASSERT(SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb); |
| 336 SkPoint pos, tan; |
| 337 for (int index = 0; index < ribs; ++index) { |
| 338 SkScalar t = (SkScalar) index / ribs; |
| 339 switch (verb) { |
| 340 case SkPath::kLine_Verb: |
| 341 tan = pts[1] - pts[0]; |
| 342 pos = pts[0]; |
| 343 pos.fX += tan.fX * t; |
| 344 pos.fY += tan.fY * t; |
| 345 break; |
| 346 case SkPath::kQuad_Verb: |
| 347 pos = SkEvalQuadAt(pts, t); |
| 348 tan = SkEvalQuadTangentAt(pts, t); |
| 349 break; |
| 350 case SkPath::kConic_Verb: { |
| 351 SkConic conic(pts, iter.conicWeight()); |
| 352 pos = conic.evalAt(t); |
| 353 tan = conic.evalTangentAt(t); |
| 354 } break; |
| 355 case SkPath::kCubic_Verb: |
| 356 SkEvalCubicAt(pts, t, &pos, &tan, nullptr); |
| 357 break; |
| 358 default: |
| 359 SkASSERT(0); |
| 360 return; |
| 361 } |
| 362 tan.setLength(radius); |
| 363 tan.rotateCCW(); |
| 364 canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(), |
| 365 pos.x() - tan.x(), pos.y() - tan.y(), paint); |
| 366 if (0 == index % 10) { |
| 367 SkString label; |
| 368 label.appendS32(index); |
| 369 canvas->drawText(label.c_str(), label.size(), |
| 370 pos.x() + tan.x() * 1.25f, pos.y() + tan.y() * 1.25f, paint)
; |
| 301 } | 371 } |
| 302 } | 372 } |
| 303 } | 373 } |
| 304 | 374 |
| 305 void draw_stroke(SkCanvas* canvas, const SkPath& path, SkScalar width, SkSca
lar scale, | 375 void draw_stroke(SkCanvas* canvas, const SkPath& path, SkScalar width, SkSca
lar scale, |
| 306 bool drawText) { | 376 bool drawText) { |
| 307 if (path.isEmpty()) { | 377 if (path.isEmpty()) { |
| 308 return; | 378 return; |
| 309 } | 379 } |
| 310 SkRect bounds = path.getBounds(); | 380 SkRect bounds = path.getBounds(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 336 } else { | 406 } else { |
| 337 scaled = path; | 407 scaled = path; |
| 338 } | 408 } |
| 339 canvas->drawPath(scaled, paint); | 409 canvas->drawPath(scaled, paint); |
| 340 draw_points(canvas, scaled, SKELETON_COLOR, true); | 410 draw_points(canvas, scaled, SKELETON_COLOR, true); |
| 341 | 411 |
| 342 if (fDrawRibs) { | 412 if (fDrawRibs) { |
| 343 draw_ribs(canvas, scaled, width, 0xFF00FF00); | 413 draw_ribs(canvas, scaled, width, 0xFF00FF00); |
| 344 } | 414 } |
| 345 | 415 |
| 416 if (fDrawTDivs) { |
| 417 draw_t_divs(canvas, scaled, width, 0xFF3F3F00); |
| 418 } |
| 419 |
| 346 SkPath fill; | 420 SkPath fill; |
| 347 | 421 |
| 348 SkPaint p; | 422 SkPaint p; |
| 349 p.setStyle(SkPaint::kStroke_Style); | 423 p.setStyle(SkPaint::kStroke_Style); |
| 350 if (drawText) { | 424 if (drawText) { |
| 351 p.setStrokeWidth(width * scale * scale); | 425 p.setStrokeWidth(width * scale * scale); |
| 352 } else { | 426 } else { |
| 353 p.setStrokeWidth(width); | 427 p.setStrokeWidth(width); |
| 354 } | 428 } |
| 355 p.getFillPath(path, &fill); | 429 p.getFillPath(path, &fill); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 paint.setTextSize(11.0f); | 495 paint.setTextSize(11.0f); |
| 422 paint.setStyle(SkPaint::kFill_Style); | 496 paint.setStyle(SkPaint::kFill_Style); |
| 423 canvas->drawText(label.c_str(), label.size(), bounds.fLeft + 5, yPos - 5
, paint); | 497 canvas->drawText(label.c_str(), label.size(), bounds.fLeft + 5, yPos - 5
, paint); |
| 424 paint.setTextSize(13.0f); | 498 paint.setTextSize(13.0f); |
| 425 canvas->drawText(name, strlen(name), bounds.fLeft, bounds.bottom() + 11,
paint); | 499 canvas->drawText(name, strlen(name), bounds.fLeft, bounds.bottom() + 11,
paint); |
| 426 } | 500 } |
| 427 | 501 |
| 428 void setForGeometry() { | 502 void setForGeometry() { |
| 429 fDrawRibs = true; | 503 fDrawRibs = true; |
| 430 fDrawTangents = true; | 504 fDrawTangents = true; |
| 505 fDrawTDivs = false; |
| 431 fWidthScale = 1; | 506 fWidthScale = 1; |
| 432 } | 507 } |
| 433 | 508 |
| 434 void setForText() { | 509 void setForText() { |
| 435 fDrawRibs = fDrawTangents = false; | 510 fDrawRibs = fDrawTangents = fDrawTDivs = false; |
| 436 fWidthScale = 0.002f; | 511 fWidthScale = 0.002f; |
| 437 } | 512 } |
| 438 | 513 |
| 514 void setForSingles() { |
| 515 setForGeometry(); |
| 516 fDrawTDivs = true; |
| 517 } |
| 518 |
| 439 void setAsNeeded() { | 519 void setAsNeeded() { |
| 440 if (fConicButton.fEnabled || fCubicButton.fEnabled || fQuadButton.fEnabl
ed | 520 if (fConicButton.fEnabled || fCubicButton.fEnabled || fQuadButton.fEnabl
ed) { |
| 441 || fRRectButton.fEnabled || fCircleButton.fEnabled) { | 521 setForSingles(); |
| 522 } else if (fRRectButton.fEnabled || fCircleButton.fEnabled) { |
| 442 setForGeometry(); | 523 setForGeometry(); |
| 443 } else { | 524 } else { |
| 444 setForText(); | 525 setForText(); |
| 445 } | 526 } |
| 446 } | 527 } |
| 447 | 528 |
| 448 void onDrawContent(SkCanvas* canvas) override { | 529 void onDrawContent(SkCanvas* canvas) override { |
| 449 SkPath path; | 530 SkPath path; |
| 450 SkScalar width = fWidth; | 531 SkScalar width = fWidth; |
| 451 | 532 |
| 452 if (fCubicButton.fEnabled) { | 533 if (fCubicButton.fEnabled) { |
| 453 path.moveTo(fPts[0]); | 534 path.moveTo(fPts[0]); |
| 454 path.cubicTo(fPts[1], fPts[2], fPts[3]); | 535 path.cubicTo(fPts[1], fPts[2], fPts[3]); |
| 455 setForGeometry(); | 536 setForSingles(); |
| 456 draw_stroke(canvas, path, width, 950, false); | 537 draw_stroke(canvas, path, width, 950, false); |
| 457 } | 538 } |
| 458 | 539 |
| 459 if (fConicButton.fEnabled) { | 540 if (fConicButton.fEnabled) { |
| 541 path.reset(); |
| 460 path.moveTo(fPts[4]); | 542 path.moveTo(fPts[4]); |
| 461 path.conicTo(fPts[5], fPts[6], fWeight); | 543 path.conicTo(fPts[5], fPts[6], fWeight); |
| 462 setForGeometry(); | 544 setForSingles(); |
| 463 draw_stroke(canvas, path, width, 950, false); | 545 draw_stroke(canvas, path, width, 950, false); |
| 464 } | 546 } |
| 465 | 547 |
| 466 if (fQuadButton.fEnabled) { | 548 if (fQuadButton.fEnabled) { |
| 467 path.reset(); | 549 path.reset(); |
| 468 path.moveTo(fPts[7]); | 550 path.moveTo(fPts[7]); |
| 469 path.quadTo(fPts[8], fPts[9]); | 551 path.quadTo(fPts[8], fPts[9]); |
| 470 setForGeometry(); | 552 setForSingles(); |
| 471 draw_stroke(canvas, path, width, 950, false); | 553 draw_stroke(canvas, path, width, 950, false); |
| 472 } | 554 } |
| 473 | 555 |
| 474 if (fRRectButton.fEnabled) { | 556 if (fRRectButton.fEnabled) { |
| 475 SkScalar rad = 32; | 557 SkScalar rad = 32; |
| 476 SkRect r; | 558 SkRect r; |
| 477 r.set(&fPts[10], 2); | 559 r.set(&fPts[10], 2); |
| 478 path.reset(); | 560 path.reset(); |
| 479 SkRRect rr; | 561 SkRRect rr; |
| 480 rr.setRectXY(r, rad, rad); | 562 rr.setRectXY(r, rad, rad); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 } | 710 } |
| 629 | 711 |
| 630 private: | 712 private: |
| 631 typedef SkView INHERITED; | 713 typedef SkView INHERITED; |
| 632 }; | 714 }; |
| 633 | 715 |
| 634 /////////////////////////////////////////////////////////////////////////////// | 716 /////////////////////////////////////////////////////////////////////////////// |
| 635 | 717 |
| 636 static SkView* F2() { return new QuadStrokerView; } | 718 static SkView* F2() { return new QuadStrokerView; } |
| 637 static SkViewRegister gR2(F2); | 719 static SkViewRegister gR2(F2); |
| OLD | NEW |