|
1 |
|
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 |
|
9 |
|
10 #include "SkDiscretePathEffect.h" |
|
11 #include "SkReadBuffer.h" |
|
12 #include "SkWriteBuffer.h" |
|
13 #include "SkPathMeasure.h" |
|
14 #include "SkRandom.h" |
|
15 |
|
16 static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) { |
|
17 SkVector normal = tangent; |
|
18 normal.rotateCCW(); |
|
19 normal.setLength(scale); |
|
20 *p += normal; |
|
21 } |
|
22 |
|
23 |
|
24 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation) |
|
25 : fSegLength(segLength), fPerterb(deviation) |
|
26 { |
|
27 } |
|
28 |
|
29 bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src, |
|
30 SkStrokeRec* rec, const SkRect*) const { |
|
31 bool doFill = rec->isFillStyle(); |
|
32 |
|
33 SkPathMeasure meas(src, doFill); |
|
34 uint32_t seed = SkScalarRoundToInt(meas.getLength()); |
|
35 SkLCGRandom rand(seed ^ ((seed << 16) | (seed >> 16))); |
|
36 SkScalar scale = fPerterb; |
|
37 SkPoint p; |
|
38 SkVector v; |
|
39 |
|
40 do { |
|
41 SkScalar length = meas.getLength(); |
|
42 |
|
43 if (fSegLength * (2 + doFill) > length) { |
|
44 meas.getSegment(0, length, dst, true); // to short for us to mangle |
|
45 } else { |
|
46 int n = SkScalarRoundToInt(length / fSegLength); |
|
47 SkScalar delta = length / n; |
|
48 SkScalar distance = 0; |
|
49 |
|
50 if (meas.isClosed()) { |
|
51 n -= 1; |
|
52 distance += delta/2; |
|
53 } |
|
54 |
|
55 if (meas.getPosTan(distance, &p, &v)) { |
|
56 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale)); |
|
57 dst->moveTo(p); |
|
58 } |
|
59 while (--n >= 0) { |
|
60 distance += delta; |
|
61 if (meas.getPosTan(distance, &p, &v)) { |
|
62 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale)); |
|
63 dst->lineTo(p); |
|
64 } |
|
65 } |
|
66 if (meas.isClosed()) { |
|
67 dst->close(); |
|
68 } |
|
69 } |
|
70 } while (meas.nextContour()); |
|
71 return true; |
|
72 } |
|
73 |
|
74 void SkDiscretePathEffect::flatten(SkWriteBuffer& buffer) const { |
|
75 this->INHERITED::flatten(buffer); |
|
76 buffer.writeScalar(fSegLength); |
|
77 buffer.writeScalar(fPerterb); |
|
78 } |
|
79 |
|
80 SkDiscretePathEffect::SkDiscretePathEffect(SkReadBuffer& buffer) { |
|
81 fSegLength = buffer.readScalar(); |
|
82 fPerterb = buffer.readScalar(); |
|
83 } |