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 void SkDiscretePathEffect::flatten(SkWriteBuffer& buffer) const { 79 this->INHERITED::flatten(buffer); 80 buffer.writeScalar(fSegLength); 81 buffer.writeScalar(fPerterb); 82 buffer.writeUInt(fSeedAssist); 83 } 84 85 SkDiscretePathEffect::SkDiscretePathEffect(SkReadBuffer& buffer) { 86 fSegLength = buffer.readScalar(); 87 fPerterb = buffer.readScalar(); 88 fSeedAssist = buffer.readUInt(); 89 } 90