OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 for (int i = 0; i < fActiveCulls.count(); ++i) { | 233 for (int i = 0; i < fActiveCulls.count(); ++i) { |
234 fActiveCulls[i]->setActive(true); | 234 fActiveCulls[i]->setActive(true); |
235 } | 235 } |
236 } | 236 } |
237 | 237 |
238 void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) { | 238 void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) { |
239 SkASSERT(!fCommandVector.isEmpty()); | 239 SkASSERT(!fCommandVector.isEmpty()); |
240 SkASSERT(index < fCommandVector.count()); | 240 SkASSERT(index < fCommandVector.count()); |
241 int i = 0; | 241 int i = 0; |
242 | 242 |
| 243 bool pathOpsMode = getAllowSimplifyClip(); |
| 244 canvas->setAllowSimplifyClip(pathOpsMode); |
243 // This only works assuming the canvas and device are the same ones that | 245 // This only works assuming the canvas and device are the same ones that |
244 // were previously drawn into because they need to preserve all saves | 246 // were previously drawn into because they need to preserve all saves |
245 // and restores. | 247 // and restores. |
246 // The visibility filter also requires a full re-draw - otherwise we can | 248 // The visibility filter also requires a full re-draw - otherwise we can |
247 // end up drawing the filter repeatedly. | 249 // end up drawing the filter repeatedly. |
248 if (fIndex < index && !fFilter && !fMegaVizMode) { | 250 if (fIndex < index && !fFilter && !fMegaVizMode && !pathOpsMode) { |
249 i = fIndex + 1; | 251 i = fIndex + 1; |
250 } else { | 252 } else { |
251 for (int j = 0; j < fOutstandingSaveCount; j++) { | 253 for (int j = 0; j < fOutstandingSaveCount; j++) { |
252 canvas->restore(); | 254 canvas->restore(); |
253 } | 255 } |
254 canvas->clear(SK_ColorTRANSPARENT); | 256 canvas->clear(SK_ColorTRANSPARENT); |
255 canvas->resetMatrix(); | 257 canvas->resetMatrix(); |
256 SkRect rect = SkRect::MakeWH(SkIntToScalar(fWidth), | 258 SkRect rect = SkRect::MakeWH(SkIntToScalar(fWidth), |
257 SkIntToScalar(fHeight)); | 259 SkIntToScalar(fHeight)); |
258 canvas->clipRect(rect, SkRegion::kReplace_Op ); | 260 canvas->clipRect(rect, SkRegion::kReplace_Op ); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 // turn off clipping | 330 // turn off clipping |
329 canvas->clipRect(r, SkRegion::kReplace_Op); | 331 canvas->clipRect(r, SkRegion::kReplace_Op); |
330 | 332 |
331 // visualize existing clips | 333 // visualize existing clips |
332 SkDebugClipVisitor visitor(canvas); | 334 SkDebugClipVisitor visitor(canvas); |
333 | 335 |
334 canvas->replayClips(&visitor); | 336 canvas->replayClips(&visitor); |
335 | 337 |
336 canvas->restore(); | 338 canvas->restore(); |
337 } | 339 } |
| 340 if (pathOpsMode) { |
| 341 this->resetClipStackData(); |
| 342 const SkClipStack* clipStack = canvas->getClipStack(); |
| 343 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart)
; |
| 344 const SkClipStack::Element* element; |
| 345 SkPath devPath; |
| 346 while ((element = iter.next())) { |
| 347 SkClipStack::Element::Type type = element->getType(); |
| 348 SkPath operand; |
| 349 if (type != SkClipStack::Element::kEmpty_Type) { |
| 350 element->asPath(&operand); |
| 351 } |
| 352 SkRegion::Op elementOp = element->getOp(); |
| 353 this->addClipStackData(devPath, operand, elementOp); |
| 354 if (elementOp == SkRegion::kReplace_Op) { |
| 355 devPath = operand; |
| 356 } else { |
| 357 Op(devPath, operand, (SkPathOp) elementOp, &devPath); |
| 358 } |
| 359 } |
| 360 this->lastClipStackData(devPath); |
| 361 } |
338 fMatrix = canvas->getTotalMatrix(); | 362 fMatrix = canvas->getTotalMatrix(); |
339 if (!canvas->getClipDeviceBounds(&fClip)) { | 363 if (!canvas->getClipDeviceBounds(&fClip)) { |
340 fClip.setEmpty(); | 364 fClip.setEmpty(); |
341 } | 365 } |
342 fIndex = index; | 366 fIndex = index; |
343 } | 367 } |
344 | 368 |
345 void SkDebugCanvas::deleteDrawCommandAt(int index) { | 369 void SkDebugCanvas::deleteDrawCommandAt(int index) { |
346 SkASSERT(index < fCommandVector.count()); | 370 SkASSERT(index < fCommandVector.count()); |
347 delete fCommandVector[index]; | 371 delete fCommandVector[index]; |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 | 605 |
582 void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) { | 606 void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) { |
583 this->addDrawCommand(new SkSetMatrixCommand(matrix)); | 607 this->addDrawCommand(new SkSetMatrixCommand(matrix)); |
584 this->INHERITED::didSetMatrix(matrix); | 608 this->INHERITED::didSetMatrix(matrix); |
585 } | 609 } |
586 | 610 |
587 void SkDebugCanvas::toggleCommand(int index, bool toggle) { | 611 void SkDebugCanvas::toggleCommand(int index, bool toggle) { |
588 SkASSERT(index < fCommandVector.count()); | 612 SkASSERT(index < fCommandVector.count()); |
589 fCommandVector[index]->setVisible(toggle); | 613 fCommandVector[index]->setVisible(toggle); |
590 } | 614 } |
| 615 |
| 616 static const char* gFillTypeStrs[] = { |
| 617 "kWinding_FillType", |
| 618 "kEvenOdd_FillType", |
| 619 "kInverseWinding_FillType", |
| 620 "kInverseEvenOdd_FillType" |
| 621 }; |
| 622 |
| 623 static const char* gOpStrs[] = { |
| 624 "kDifference_PathOp", |
| 625 "kIntersect_PathOp", |
| 626 "kUnion_PathOp", |
| 627 "kXor_PathOp", |
| 628 "kReverseDifference_PathOp", |
| 629 }; |
| 630 |
| 631 static const char kHTML4SpaceIndent[] = " "; |
| 632 |
| 633 void SkDebugCanvas::outputScalar(SkScalar num) { |
| 634 if (num == (int) num) { |
| 635 fClipStackData.appendf("%d", (int) num); |
| 636 } else { |
| 637 SkString str; |
| 638 str.printf("%1.9g", num); |
| 639 int width = (int) str.size(); |
| 640 const char* cStr = str.c_str(); |
| 641 while (cStr[width - 1] == '0') { |
| 642 --width; |
| 643 } |
| 644 str.resize(width); |
| 645 fClipStackData.appendf("%sf", str.c_str()); |
| 646 } |
| 647 } |
| 648 |
| 649 void SkDebugCanvas::outputPointsCommon(const SkPoint* pts, int count) { |
| 650 for (int index = 0; index < count; ++index) { |
| 651 this->outputScalar(pts[index].fX); |
| 652 fClipStackData.appendf(", "); |
| 653 this->outputScalar(pts[index].fY); |
| 654 if (index + 1 < count) { |
| 655 fClipStackData.appendf(", "); |
| 656 } |
| 657 } |
| 658 } |
| 659 |
| 660 void SkDebugCanvas::outputPoints(const SkPoint* pts, int count) { |
| 661 this->outputPointsCommon(pts, count); |
| 662 fClipStackData.appendf(");<br>"); |
| 663 } |
| 664 |
| 665 void SkDebugCanvas::outputConicPoints(const SkPoint* pts, SkScalar weight) { |
| 666 this->outputPointsCommon(pts, 2); |
| 667 fClipStackData.appendf(", "); |
| 668 this->outputScalar(weight); |
| 669 fClipStackData.appendf(");<br>"); |
| 670 } |
| 671 |
| 672 void SkDebugCanvas::addPathData(const SkPath& path, const char* pathName) { |
| 673 SkPath::RawIter iter(path); |
| 674 SkPath::FillType fillType = path.getFillType(); |
| 675 fClipStackData.appendf("%sSkPath %s;<br>", kHTML4SpaceIndent, pathName); |
| 676 fClipStackData.appendf("%s%s.setFillType(SkPath::%s);<br>", kHTML4SpaceInden
t, pathName, |
| 677 gFillTypeStrs[fillType]); |
| 678 iter.setPath(path); |
| 679 uint8_t verb; |
| 680 SkPoint pts[4]; |
| 681 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
| 682 switch (verb) { |
| 683 case SkPath::kMove_Verb: |
| 684 fClipStackData.appendf("%s%s.moveTo(", kHTML4SpaceIndent, pathNa
me); |
| 685 this->outputPoints(&pts[0], 1); |
| 686 continue; |
| 687 case SkPath::kLine_Verb: |
| 688 fClipStackData.appendf("%s%s.lineTo(", kHTML4SpaceIndent, pathNa
me); |
| 689 this->outputPoints(&pts[1], 1); |
| 690 break; |
| 691 case SkPath::kQuad_Verb: |
| 692 fClipStackData.appendf("%s%s.quadTo(", kHTML4SpaceIndent, pathNa
me); |
| 693 this->outputPoints(&pts[1], 2); |
| 694 break; |
| 695 case SkPath::kConic_Verb: |
| 696 fClipStackData.appendf("%s%s.conicTo(", kHTML4SpaceIndent, pathN
ame); |
| 697 this->outputConicPoints(&pts[1], iter.conicWeight()); |
| 698 break; |
| 699 case SkPath::kCubic_Verb: |
| 700 fClipStackData.appendf("%s%s.cubicTo(", kHTML4SpaceIndent, pathN
ame); |
| 701 this->outputPoints(&pts[1], 3); |
| 702 break; |
| 703 case SkPath::kClose_Verb: |
| 704 fClipStackData.appendf("%s%s.close();<br>", kHTML4SpaceIndent, p
athName); |
| 705 break; |
| 706 default: |
| 707 SkDEBUGFAIL("bad verb"); |
| 708 return; |
| 709 } |
| 710 } |
| 711 } |
| 712 |
| 713 void SkDebugCanvas::addClipStackData(const SkPath& devPath, const SkPath& operan
d, |
| 714 SkRegion::Op elementOp) { |
| 715 if (elementOp == SkRegion::kReplace_Op) { |
| 716 if (!lastClipStackData(devPath)) { |
| 717 fSaveDevPath = operand; |
| 718 } |
| 719 fCalledAddStackData = false; |
| 720 } else { |
| 721 fClipStackData.appendf("<br>static void test(skiatest::Reporter* reporte
r," |
| 722 " const char* filename) {<br>"); |
| 723 addPathData(fCalledAddStackData ? devPath : fSaveDevPath, "path"); |
| 724 addPathData(operand, "pathB"); |
| 725 fClipStackData.appendf("%stestPathOp(reporter, path, pathB, %s, filename
);<br>", |
| 726 kHTML4SpaceIndent, gOpStrs[elementOp]); |
| 727 fClipStackData.appendf("}<br>"); |
| 728 fCalledAddStackData = true; |
| 729 } |
| 730 } |
| 731 |
| 732 bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) { |
| 733 if (fCalledAddStackData) { |
| 734 fClipStackData.appendf("<br>"); |
| 735 addPathData(devPath, "pathOut"); |
| 736 return true; |
| 737 } |
| 738 return false; |
| 739 } |
OLD | NEW |