SkDiscretePathEffect.cpp revision 56d5bfa90eb8fdfdef65bc91276480036bc545b6
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 15static 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 23SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation) 24 : fSegLength(segLength), fPerterb(deviation) 25{ 26} 27 28bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src, 29 SkStrokeRec* rec) { 30 bool doFill = rec->isFillStyle(); 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 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 73void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) const { 74 this->INHERITED::flatten(buffer); 75 buffer.writeScalar(fSegLength); 76 buffer.writeScalar(fPerterb); 77} 78 79SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) { 80 fSegLength = buffer.readScalar(); 81 fPerterb = buffer.readScalar(); 82} 83 84/////////////////////////////////////////////////////////////////////////////// 85 86SK_DEFINE_FLATTENABLE_REGISTRAR(SkDiscretePathEffect) 87 88