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 23 static 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 32 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation) 33 : fSegLength(segLength), fPerterb(deviation) 34 { 35 } 36 37 bool 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 83 SkFlattenable::Factory SkDiscretePathEffect::getFactory() 84 { 85 return CreateProc; 86 } 87 88 SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) 89 { 90 return SkNEW_ARGS(SkDiscretePathEffect, (buffer)); 91 } 92 93 void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) 94 { 95 buffer.writeScalar(fSegLength); 96 buffer.writeScalar(fPerterb); 97 } 98 99 SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) 100 { 101 fSegLength = buffer.readScalar(); 102 fPerterb = buffer.readScalar(); 103 } 104 105 106