SkCornerPathEffect.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright 2006 The Android Open Source Project
  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 "include/core/SkPath.h"
  8. #include "include/core/SkPoint.h"
  9. #include "include/effects/SkCornerPathEffect.h"
  10. #include "src/core/SkReadBuffer.h"
  11. #include "src/core/SkWriteBuffer.h"
  12. SkCornerPathEffect::SkCornerPathEffect(SkScalar radius) {
  13. // check with ! to catch NaNs
  14. if (!(radius > 0)) {
  15. radius = 0;
  16. }
  17. fRadius = radius;
  18. }
  19. SkCornerPathEffect::~SkCornerPathEffect() {}
  20. static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius,
  21. SkPoint* step) {
  22. SkScalar dist = SkPoint::Distance(a, b);
  23. *step = b - a;
  24. if (dist <= radius * 2) {
  25. *step *= SK_ScalarHalf;
  26. return false;
  27. } else {
  28. *step *= radius / dist;
  29. return true;
  30. }
  31. }
  32. bool SkCornerPathEffect::onFilterPath(SkPath* dst, const SkPath& src,
  33. SkStrokeRec*, const SkRect*) const {
  34. if (fRadius <= 0) {
  35. return false;
  36. }
  37. SkPath::Iter iter(src, false);
  38. SkPath::Verb verb, prevVerb = SkPath::kDone_Verb;
  39. SkPoint pts[4];
  40. bool closed;
  41. SkPoint moveTo, lastCorner;
  42. SkVector firstStep, step;
  43. bool prevIsValid = true;
  44. // to avoid warnings
  45. step.set(0, 0);
  46. moveTo.set(0, 0);
  47. firstStep.set(0, 0);
  48. lastCorner.set(0, 0);
  49. for (;;) {
  50. switch (verb = iter.next(pts, false)) {
  51. case SkPath::kMove_Verb:
  52. // close out the previous (open) contour
  53. if (SkPath::kLine_Verb == prevVerb) {
  54. dst->lineTo(lastCorner);
  55. }
  56. closed = iter.isClosedContour();
  57. if (closed) {
  58. moveTo = pts[0];
  59. prevIsValid = false;
  60. } else {
  61. dst->moveTo(pts[0]);
  62. prevIsValid = true;
  63. }
  64. break;
  65. case SkPath::kLine_Verb: {
  66. bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step);
  67. // prev corner
  68. if (!prevIsValid) {
  69. dst->moveTo(moveTo + step);
  70. prevIsValid = true;
  71. } else {
  72. dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX,
  73. pts[0].fY + step.fY);
  74. }
  75. if (drawSegment) {
  76. dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY);
  77. }
  78. lastCorner = pts[1];
  79. prevIsValid = true;
  80. break;
  81. }
  82. case SkPath::kQuad_Verb:
  83. // TBD - just replicate the curve for now
  84. if (!prevIsValid) {
  85. dst->moveTo(pts[0]);
  86. prevIsValid = true;
  87. }
  88. dst->quadTo(pts[1], pts[2]);
  89. lastCorner = pts[2];
  90. firstStep.set(0, 0);
  91. break;
  92. case SkPath::kConic_Verb:
  93. // TBD - just replicate the curve for now
  94. if (!prevIsValid) {
  95. dst->moveTo(pts[0]);
  96. prevIsValid = true;
  97. }
  98. dst->conicTo(pts[1], pts[2], iter.conicWeight());
  99. lastCorner = pts[2];
  100. firstStep.set(0, 0);
  101. break;
  102. case SkPath::kCubic_Verb:
  103. if (!prevIsValid) {
  104. dst->moveTo(pts[0]);
  105. prevIsValid = true;
  106. }
  107. // TBD - just replicate the curve for now
  108. dst->cubicTo(pts[1], pts[2], pts[3]);
  109. lastCorner = pts[3];
  110. firstStep.set(0, 0);
  111. break;
  112. case SkPath::kClose_Verb:
  113. if (firstStep.fX || firstStep.fY) {
  114. dst->quadTo(lastCorner.fX, lastCorner.fY,
  115. lastCorner.fX + firstStep.fX,
  116. lastCorner.fY + firstStep.fY);
  117. }
  118. dst->close();
  119. prevIsValid = false;
  120. break;
  121. case SkPath::kDone_Verb:
  122. if (prevIsValid) {
  123. dst->lineTo(lastCorner);
  124. }
  125. return true;
  126. default:
  127. SkDEBUGFAIL("default should not be reached");
  128. return false;
  129. }
  130. if (SkPath::kMove_Verb == prevVerb) {
  131. firstStep = step;
  132. }
  133. prevVerb = verb;
  134. }
  135. return true;
  136. }
  137. sk_sp<SkFlattenable> SkCornerPathEffect::CreateProc(SkReadBuffer& buffer) {
  138. return SkCornerPathEffect::Make(buffer.readScalar());
  139. }
  140. void SkCornerPathEffect::flatten(SkWriteBuffer& buffer) const {
  141. buffer.writeScalar(fRadius);
  142. }