Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / SkDiscretePathEffect.cpp
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 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength,
24                                            SkScalar deviation,
25                                            uint32_t seedAssist)
26     : fSegLength(segLength), fPerterb(deviation), fSeedAssist(seedAssist)
27 {
28 }
29
30 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
78 SkFlattenable* SkDiscretePathEffect::CreateProc(SkReadBuffer& buffer) {
79     SkScalar segLength = buffer.readScalar();
80     SkScalar perterb = buffer.readScalar();
81     uint32_t seed = buffer.readUInt();
82     return Create(segLength, perterb, seed);
83 }
84
85 void SkDiscretePathEffect::flatten(SkWriteBuffer& buffer) const {
86     buffer.writeScalar(fSegLength);
87     buffer.writeScalar(fPerterb);
88     buffer.writeUInt(fSeedAssist);
89 }
90
91 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
92 SkDiscretePathEffect::SkDiscretePathEffect(SkReadBuffer& buffer) {
93     fSegLength = buffer.readScalar();
94     fPerterb = buffer.readScalar();
95     fSeedAssist = buffer.readUInt();
96 }
97 #endif
98