1/* libs/graphics/effects/SkDiscretePathEffect.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "SkDiscretePathEffect.h" 19#include "SkBuffer.h" 20#include "SkPathMeasure.h" 21#include "SkRandom.h" 22 23static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) 24{ 25 SkVector normal = tangent; 26 normal.rotateCCW(); 27 normal.setLength(scale); 28 *p += normal; 29} 30 31 32SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation) 33 : fSegLength(segLength), fPerterb(deviation) 34{ 35} 36 37bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width) 38{ 39 bool doFill = *width < 0; 40 41 SkPathMeasure meas(src, doFill); 42 uint32_t seed = SkScalarRound(meas.getLength()); 43 SkRandom rand(seed ^ ((seed << 16) | (seed >> 16))); 44 SkScalar scale = fPerterb; 45 SkPoint p; 46 SkVector v; 47 48 do { 49 SkScalar length = meas.getLength(); 50 51 if (fSegLength * (2 + doFill) > length) 52 { 53 meas.getSegment(0, length, dst, true); // to short for us to mangle 54 } 55 else 56 { 57 int n = SkScalarRound(SkScalarDiv(length, fSegLength)); 58 SkScalar delta = length / n; 59 SkScalar distance = 0; 60 61 if (meas.isClosed()) 62 { 63 n -= 1; 64 distance += delta/2; 65 } 66 meas.getPosTan(distance, &p, &v); 67 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale)); 68 dst->moveTo(p); 69 while (--n >= 0) 70 { 71 distance += delta; 72 meas.getPosTan(distance, &p, &v); 73 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale)); 74 dst->lineTo(p); 75 } 76 if (meas.isClosed()) 77 dst->close(); 78 } 79 } while (meas.nextContour()); 80 return true; 81} 82 83SkFlattenable::Factory SkDiscretePathEffect::getFactory() 84{ 85 return CreateProc; 86} 87 88SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) 89{ 90 return SkNEW_ARGS(SkDiscretePathEffect, (buffer)); 91} 92 93void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) 94{ 95 buffer.writeScalar(fSegLength); 96 buffer.writeScalar(fPerterb); 97} 98 99SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) 100{ 101 fSegLength = buffer.readScalar(); 102 fPerterb = buffer.readScalar(); 103} 104 105 106