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 "SkFlattenableBuffers.h" 12 #include "SkPathMeasure.h" 13 #include "SkRandom.h" 14 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 23 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation) 24 : fSegLength(segLength), fPerterb(deviation) 25 { 26 } 27 28 bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src, 29 SkStrokeRec* rec, const SkRect*) const { 30 bool doFill = rec->isFillStyle(); 31 32 SkPathMeasure meas(src, doFill); 33 uint32_t seed = SkScalarRound(meas.getLength()); 34 SkLCGRandom 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 54 if (meas.getPosTan(distance, &p, &v)) { 55 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale)); 56 dst->moveTo(p); 57 } 58 while (--n >= 0) { 59 distance += delta; 60 if (meas.getPosTan(distance, &p, &v)) { 61 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale)); 62 dst->lineTo(p); 63 } 64 } 65 if (meas.isClosed()) { 66 dst->close(); 67 } 68 } 69 } while (meas.nextContour()); 70 return true; 71 } 72 73 void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) const { 74 this->INHERITED::flatten(buffer); 75 buffer.writeScalar(fSegLength); 76 buffer.writeScalar(fPerterb); 77 } 78 79 SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) { 80 fSegLength = buffer.readScalar(); 81 fPerterb = buffer.readScalar(); 82 } 83