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 SkVector normal = tangent; 25 normal.rotateCCW(); 26 normal.setLength(scale); 27 *p += normal; 28 } 29 30 31 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation) 32 : fSegLength(segLength), fPerterb(deviation) 33 { 34 } 35 36 bool 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 78 SkFlattenable::Factory SkDiscretePathEffect::getFactory() { 79 return CreateProc; 80 } 81 82 SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) { 83 return SkNEW_ARGS(SkDiscretePathEffect, (buffer)); 84 } 85 86 void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) { 87 buffer.writeScalar(fSegLength); 88 buffer.writeScalar(fPerterb); 89 } 90 91 SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) { 92 fSegLength = buffer.readScalar(); 93 fPerterb = buffer.readScalar(); 94 } 95 96