1 /* libs/graphics/effects/SkDiscretePathEffect.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkDiscretePathEffect.h"
19 #include "SkBuffer.h"
20 #include "SkPathMeasure.h"
21 #include "SkRandom.h"
22
Perterb(SkPoint * p,const SkVector & tangent,SkScalar scale)23 static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale)
24 {
25 SkVector normal = tangent;
26 normal.rotateCCW();
27 normal.setLength(scale);
28 *p += normal;
29 }
30
31
SkDiscretePathEffect(SkScalar segLength,SkScalar deviation)32 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
33 : fSegLength(segLength), fPerterb(deviation)
34 {
35 }
36
filterPath(SkPath * dst,const SkPath & src,SkScalar * width)37 bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
38 {
39 bool doFill = *width < 0;
40
41 SkPathMeasure meas(src, doFill);
42 uint32_t seed = SkScalarRound(meas.getLength());
43 SkRandom rand(seed ^ ((seed << 16) | (seed >> 16)));
44 SkScalar scale = fPerterb;
45 SkPoint p;
46 SkVector v;
47
48 do {
49 SkScalar length = meas.getLength();
50
51 if (fSegLength * (2 + doFill) > length)
52 {
53 meas.getSegment(0, length, dst, true); // to short for us to mangle
54 }
55 else
56 {
57 int n = SkScalarRound(SkScalarDiv(length, fSegLength));
58 SkScalar delta = length / n;
59 SkScalar distance = 0;
60
61 if (meas.isClosed())
62 {
63 n -= 1;
64 distance += delta/2;
65 }
66 meas.getPosTan(distance, &p, &v);
67 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
68 dst->moveTo(p);
69 while (--n >= 0)
70 {
71 distance += delta;
72 meas.getPosTan(distance, &p, &v);
73 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
74 dst->lineTo(p);
75 }
76 if (meas.isClosed())
77 dst->close();
78 }
79 } while (meas.nextContour());
80 return true;
81 }
82
getFactory()83 SkFlattenable::Factory SkDiscretePathEffect::getFactory()
84 {
85 return CreateProc;
86 }
87
CreateProc(SkFlattenableReadBuffer & buffer)88 SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer)
89 {
90 return SkNEW_ARGS(SkDiscretePathEffect, (buffer));
91 }
92
flatten(SkFlattenableWriteBuffer & buffer)93 void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer)
94 {
95 buffer.writeScalar(fSegLength);
96 buffer.writeScalar(fPerterb);
97 }
98
SkDiscretePathEffect(SkFlattenableReadBuffer & buffer)99 SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer)
100 {
101 fSegLength = buffer.readScalar();
102 fPerterb = buffer.readScalar();
103 }
104
105
106