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 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 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 70 SkFlattenable::Factory SkDiscretePathEffect::getFactory() { 71 return CreateProc; 72 } 73 74 SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) { 75 return SkNEW_ARGS(SkDiscretePathEffect, (buffer)); 76 } 77 78 void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) { 79 buffer.writeScalar(fSegLength); 80 buffer.writeScalar(fPerterb); 81 } 82 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