SkDiscretePathEffect.cpp revision 35e2e62b55598210f6999fc2ea26ff8f41446ffe
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 SkVector normal = tangent; 25 normal.rotateCCW(); 26 normal.setLength(scale); 27 *p += normal; 28} 29 30 31SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation) 32 : fSegLength(segLength), fPerterb(deviation) 33{ 34} 35 36bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src, 37 SkScalar* width) { 38 bool doFill = *width < 0; 39 40 SkPathMeasure meas(src, doFill); 41 uint32_t seed = SkScalarRound(meas.getLength()); 42 SkRandom rand(seed ^ ((seed << 16) | (seed >> 16))); 43 SkScalar scale = fPerterb; 44 SkPoint p; 45 SkVector v; 46 47 do { 48 SkScalar length = meas.getLength(); 49 50 if (fSegLength * (2 + doFill) > length) { 51 meas.getSegment(0, length, dst, true); // to short for us to mangle 52 } else { 53 int n = SkScalarRound(SkScalarDiv(length, fSegLength)); 54 SkScalar delta = length / n; 55 SkScalar distance = 0; 56 57 if (meas.isClosed()) { 58 n -= 1; 59 distance += delta/2; 60 } 61 meas.getPosTan(distance, &p, &v); 62 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale)); 63 dst->moveTo(p); 64 while (--n >= 0) { 65 distance += delta; 66 meas.getPosTan(distance, &p, &v); 67 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale)); 68 dst->lineTo(p); 69 } 70 if (meas.isClosed()) { 71 dst->close(); 72 } 73 } 74 } while (meas.nextContour()); 75 return true; 76} 77 78SkFlattenable::Factory SkDiscretePathEffect::getFactory() { 79 return CreateProc; 80} 81 82SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) { 83 return SkNEW_ARGS(SkDiscretePathEffect, (buffer)); 84} 85 86void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) { 87 buffer.writeScalar(fSegLength); 88 buffer.writeScalar(fPerterb); 89} 90 91SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) { 92 fSegLength = buffer.readScalar(); 93 fPerterb = buffer.readScalar(); 94} 95 96