blob: 089bed67574e596d7e8e7b2d69952abc77b8f303 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkDiscretePathEffect.h"
11#include "SkBuffer.h"
12#include "SkPathMeasure.h"
13#include "SkRandom.h"
14
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000015static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000016 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
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000028bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
29 SkScalar* width) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000030 bool doFill = *width < 0;
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
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000042 if (fSegLength * (2 + doFill) > length) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000043 meas.getSegment(0, length, dst, true); // to short for us to mangle
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000044 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000045 int n = SkScalarRound(SkScalarDiv(length, fSegLength));
46 SkScalar delta = length / n;
47 SkScalar distance = 0;
48
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000049 if (meas.isClosed()) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000050 n -= 1;
51 distance += delta/2;
52 }
53 meas.getPosTan(distance, &p, &v);
54 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
55 dst->moveTo(p);
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000056 while (--n >= 0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000057 distance += delta;
58 meas.getPosTan(distance, &p, &v);
59 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
60 dst->lineTo(p);
61 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000062 if (meas.isClosed()) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000063 dst->close();
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000064 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000065 }
66 } while (meas.nextContour());
67 return true;
68}
69
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000070void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 buffer.writeScalar(fSegLength);
72 buffer.writeScalar(fPerterb);
73}
74
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000075SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 fSegLength = buffer.readScalar();
77 fPerterb = buffer.readScalar();
78}
79
reed@google.com6bac9472011-06-21 19:24:00 +000080///////////////////////////////////////////////////////////////////////////////
81
caryclark@google.comd26147a2011-12-15 14:16:43 +000082SK_DEFINE_FLATTENABLE_REGISTRAR(SkDiscretePathEffect)
reed@google.com6bac9472011-06-21 19:24:00 +000083