blob: de834424df34fc661638fcbb7026bdc8214571a7 [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"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000011#include "SkReadBuffer.h"
12#include "SkWriteBuffer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkPathMeasure.h"
14#include "SkRandom.h"
15
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000016static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000017 SkVector normal = tangent;
18 normal.rotateCCW();
19 normal.setLength(scale);
20 *p += normal;
21}
22
23
24SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
25 : fSegLength(segLength), fPerterb(deviation)
26{
27}
28
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000029bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
reed@google.com4bbdeac2013-01-24 21:03:11 +000030 SkStrokeRec* rec, const SkRect*) const {
reed@google.comfd4be262012-05-25 01:04:12 +000031 bool doFill = rec->isFillStyle();
reed@android.com8a1c16f2008-12-17 15:59:43 +000032
33 SkPathMeasure meas(src, doFill);
reed@google.come1ca7052013-12-17 19:22:07 +000034 uint32_t seed = SkScalarRoundToInt(meas.getLength());
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000035 SkLCGRandom rand(seed ^ ((seed << 16) | (seed >> 16)));
reed@android.com8a1c16f2008-12-17 15:59:43 +000036 SkScalar scale = fPerterb;
37 SkPoint p;
38 SkVector v;
39
40 do {
41 SkScalar length = meas.getLength();
42
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000043 if (fSegLength * (2 + doFill) > length) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 meas.getSegment(0, length, dst, true); // to short for us to mangle
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000045 } else {
reed@google.come1ca7052013-12-17 19:22:07 +000046 int n = SkScalarRoundToInt(length / fSegLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +000047 SkScalar delta = length / n;
48 SkScalar distance = 0;
49
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000050 if (meas.isClosed()) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 n -= 1;
52 distance += delta/2;
53 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000054
reed@google.comf3edf9f2012-04-12 19:44:38 +000055 if (meas.getPosTan(distance, &p, &v)) {
56 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
57 dst->moveTo(p);
58 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000059 while (--n >= 0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000060 distance += delta;
reed@google.comf3edf9f2012-04-12 19:44:38 +000061 if (meas.getPosTan(distance, &p, &v)) {
62 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
63 dst->lineTo(p);
64 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000065 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000066 if (meas.isClosed()) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 dst->close();
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000068 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 }
70 } while (meas.nextContour());
71 return true;
72}
73
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000074void SkDiscretePathEffect::flatten(SkWriteBuffer& buffer) const {
djsollen@google.com54924242012-03-29 15:18:04 +000075 this->INHERITED::flatten(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 buffer.writeScalar(fSegLength);
77 buffer.writeScalar(fPerterb);
78}
79
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000080SkDiscretePathEffect::SkDiscretePathEffect(SkReadBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000081 fSegLength = buffer.readScalar();
82 fPerterb = buffer.readScalar();
83}