• 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 "SkBuffer.h"
12 #include "SkPathMeasure.h"
13 #include "SkRandom.h"
14 
Perterb(SkPoint * p,const SkVector & tangent,SkScalar scale)15 static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
16     SkVector normal = tangent;
17     normal.rotateCCW();
18     normal.setLength(scale);
19     *p += normal;
20 }
21 
22 
SkDiscretePathEffect(SkScalar segLength,SkScalar deviation)23 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
24     : fSegLength(segLength), fPerterb(deviation)
25 {
26 }
27 
filterPath(SkPath * dst,const SkPath & src,SkScalar * width)28 bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
29                                       SkScalar* width) {
30     bool doFill = *width < 0;
31 
32     SkPathMeasure   meas(src, doFill);
33     uint32_t        seed = SkScalarRound(meas.getLength());
34     SkRandom        rand(seed ^ ((seed << 16) | (seed >> 16)));
35     SkScalar        scale = fPerterb;
36     SkPoint         p;
37     SkVector        v;
38 
39     do {
40         SkScalar    length = meas.getLength();
41 
42         if (fSegLength * (2 + doFill) > length) {
43             meas.getSegment(0, length, dst, true);  // to short for us to mangle
44         } else {
45             int         n = SkScalarRound(SkScalarDiv(length, fSegLength));
46             SkScalar    delta = length / n;
47             SkScalar    distance = 0;
48 
49             if (meas.isClosed()) {
50                 n -= 1;
51                 distance += delta/2;
52             }
53             meas.getPosTan(distance, &p, &v);
54             Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
55             dst->moveTo(p);
56             while (--n >= 0) {
57                 distance += delta;
58                 meas.getPosTan(distance, &p, &v);
59                 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
60                 dst->lineTo(p);
61             }
62             if (meas.isClosed()) {
63                 dst->close();
64             }
65         }
66     } while (meas.nextContour());
67     return true;
68 }
69 
getFactory()70 SkFlattenable::Factory SkDiscretePathEffect::getFactory() {
71     return CreateProc;
72 }
73 
CreateProc(SkFlattenableReadBuffer & buffer)74 SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) {
75     return SkNEW_ARGS(SkDiscretePathEffect, (buffer));
76 }
77 
flatten(SkFlattenableWriteBuffer & buffer)78 void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
79     buffer.writeScalar(fSegLength);
80     buffer.writeScalar(fPerterb);
81 }
82 
SkDiscretePathEffect(SkFlattenableReadBuffer & buffer)83 SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) {
84     fSegLength = buffer.readScalar();
85     fPerterb = buffer.readScalar();
86 }
87 
88 ///////////////////////////////////////////////////////////////////////////////
89 
90 SK_DEFINE_FLATTENABLE_REGISTRAR(SkDiscretePathEffect)
91 
92