• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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