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
Perterb(SkPoint * p,const SkVector & tangent,SkScalar scale)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
SkDiscretePathEffect(SkScalar segLength,SkScalar deviation,uint32_t seedAssist)23 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength,
24 SkScalar deviation,
25 uint32_t seedAssist)
26 : fSegLength(segLength), fPerterb(deviation), fSeedAssist(seedAssist)
27 {
28 }
29
filterPath(SkPath * dst,const SkPath & src,SkStrokeRec * rec,const SkRect *) const30 bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
31 SkStrokeRec* rec, const SkRect*) const {
32 bool doFill = rec->isFillStyle();
33
34 SkPathMeasure meas(src, doFill);
35
36 /* Caller may supply their own seed assist, which by default is 0 */
37 uint32_t seed = fSeedAssist ^ SkScalarRoundToInt(meas.getLength());
38
39 SkLCGRandom rand(seed ^ ((seed << 16) | (seed >> 16)));
40 SkScalar scale = fPerterb;
41 SkPoint p;
42 SkVector v;
43
44 do {
45 SkScalar length = meas.getLength();
46
47 if (fSegLength * (2 + doFill) > length) {
48 meas.getSegment(0, length, dst, true); // to short for us to mangle
49 } else {
50 int n = SkScalarRoundToInt(length / fSegLength);
51 SkScalar delta = length / n;
52 SkScalar distance = 0;
53
54 if (meas.isClosed()) {
55 n -= 1;
56 distance += delta/2;
57 }
58
59 if (meas.getPosTan(distance, &p, &v)) {
60 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
61 dst->moveTo(p);
62 }
63 while (--n >= 0) {
64 distance += delta;
65 if (meas.getPosTan(distance, &p, &v)) {
66 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
67 dst->lineTo(p);
68 }
69 }
70 if (meas.isClosed()) {
71 dst->close();
72 }
73 }
74 } while (meas.nextContour());
75 return true;
76 }
77
flatten(SkWriteBuffer & buffer) const78 void SkDiscretePathEffect::flatten(SkWriteBuffer& buffer) const {
79 this->INHERITED::flatten(buffer);
80 buffer.writeScalar(fSegLength);
81 buffer.writeScalar(fPerterb);
82 buffer.writeUInt(fSeedAssist);
83 }
84
SkDiscretePathEffect(SkReadBuffer & buffer)85 SkDiscretePathEffect::SkDiscretePathEffect(SkReadBuffer& buffer) {
86 fSegLength = buffer.readScalar();
87 fPerterb = buffer.readScalar();
88 fSeedAssist = buffer.readUInt();
89 }
90