blob: 62860455a365dcf412b87116c3035f8000fab0ca [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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
23static 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
32SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
33 : fSegLength(segLength), fPerterb(deviation)
34{
35}
36
37bool 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
83SkFlattenable::Factory SkDiscretePathEffect::getFactory()
84{
85 return CreateProc;
86}
87
88SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer)
89{
90 return SkNEW_ARGS(SkDiscretePathEffect, (buffer));
91}
92
93void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer)
94{
95 buffer.writeScalar(fSegLength);
96 buffer.writeScalar(fPerterb);
97}
98
99SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer)
100{
101 fSegLength = buffer.readScalar();
102 fPerterb = buffer.readScalar();
103}
104
105