blob: 5eb94a438fcbb6fb2247fe2a67dd9fa25b0da6e6 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2006 The Android Open Source Project
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkCornerPathEffect.h"
11#include "SkPath.h"
12#include "SkPoint.h"
13#include "SkBuffer.h"
14
15SkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius)
16{
17}
18
19SkCornerPathEffect::~SkCornerPathEffect()
20{
21}
22
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000023static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius,
24 SkPoint* step) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000025 SkScalar dist = SkPoint::Distance(a, b);
26
27 step->set(b.fX - a.fX, b.fY - a.fY);
28
29 if (dist <= radius * 2) {
30 step->scale(SK_ScalarHalf);
31 return false;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000032 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000033 step->scale(SkScalarDiv(radius, dist));
34 return true;
35 }
36}
37
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000038bool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src,
39 SkScalar* width) {
40 if (fRadius == 0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000041 return false;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000042 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000043
44 SkPath::Iter iter(src, false);
45 SkPath::Verb verb, prevVerb = (SkPath::Verb)-1;
46 SkPoint pts[4];
47
48 bool closed;
49 SkPoint moveTo, lastCorner;
50 SkVector firstStep, step;
51 bool prevIsValid = true;
52
53 // to avoid warnings
54 moveTo.set(0, 0);
55 firstStep.set(0, 0);
56 lastCorner.set(0, 0);
57
58 for (;;) {
59 switch (verb = iter.next(pts)) {
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000060 case SkPath::kMove_Verb:
61 // close out the previous (open) contour
62 if (SkPath::kLine_Verb == prevVerb) {
63 dst->lineTo(lastCorner);
64 }
65 closed = iter.isClosedContour();
66 if (closed) {
67 moveTo = pts[0];
68 prevIsValid = false;
69 } else {
70 dst->moveTo(pts[0]);
71 prevIsValid = true;
72 }
73 break;
74 case SkPath::kLine_Verb: {
reed@android.com8a1c16f2008-12-17 15:59:43 +000075 bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step);
76 // prev corner
77 if (!prevIsValid) {
78 dst->moveTo(moveTo + step);
79 prevIsValid = true;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000080 } else {
81 dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX,
82 pts[0].fY + step.fY);
reed@android.com8a1c16f2008-12-17 15:59:43 +000083 }
84 if (drawSegment) {
85 dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY);
86 }
87 lastCorner = pts[1];
88 prevIsValid = true;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000089 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +000090 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000091 case SkPath::kQuad_Verb:
92 // TBD - just replicate the curve for now
93 if (!prevIsValid) {
94 dst->moveTo(pts[0]);
95 prevIsValid = true;
96 }
97 dst->quadTo(pts[1], pts[2]);
98 lastCorner = pts[2];
99 firstStep.set(0, 0);
100 break;
101 case SkPath::kCubic_Verb:
102 if (!prevIsValid) {
103 dst->moveTo(pts[0]);
104 prevIsValid = true;
105 }
106 // TBD - just replicate the curve for now
107 dst->cubicTo(pts[1], pts[2], pts[3]);
108 lastCorner = pts[3];
109 firstStep.set(0, 0);
110 break;
111 case SkPath::kClose_Verb:
112 if (firstStep.fX || firstStep.fY) {
113 dst->quadTo(lastCorner.fX, lastCorner.fY,
114 lastCorner.fX + firstStep.fX,
115 lastCorner.fY + firstStep.fY);
116 }
117 dst->close();
118 break;
119 case SkPath::kDone_Verb:
120 goto DONE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121 }
122
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000123 if (SkPath::kMove_Verb == prevVerb) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 firstStep = step;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000125 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000126 prevVerb = verb;
127 }
128DONE:
129 return true;
130}
131
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000132void SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133 buffer.writeScalar(fRadius);
134}
135
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000136SkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137 fRadius = buffer.readScalar();
138}
139
caryclark@google.comd26147a2011-12-15 14:16:43 +0000140SK_DEFINE_FLATTENABLE_REGISTRAR(SkCornerPathEffect)
reed@google.com6bac9472011-06-21 19:24:00 +0000141