SkDiscretePathEffect.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
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
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
106