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