1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/*
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com *
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */
8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkDiscretePathEffect.h"
119ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkFlattenableBuffers.h"
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPathMeasure.h"
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkRandom.h"
14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
156c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.orgstatic void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkVector normal = tangent;
17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    normal.rotateCCW();
18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    normal.setLength(scale);
19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    *p += normal;
20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    : fSegLength(segLength), fPerterb(deviation)
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
286c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.orgbool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
29bb77acf17c4eb4f58b6bfbe48d750d018485ecf2reed@google.com                                      SkStrokeRec* rec, const SkRect*) const {
30d49b87f7307690e47c5cb093ff9d7cce4f009e87reed@google.com    bool doFill = rec->isFillStyle();
31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkPathMeasure   meas(src, doFill);
33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t        seed = SkScalarRound(meas.getLength());
34680372190ee596c7485dcf2974c824fcf6a355dccommit-bot@chromium.org    SkLCGRandom     rand(seed ^ ((seed << 16) | (seed >> 16)));
35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkScalar        scale = fPerterb;
36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkPoint         p;
37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkVector        v;
38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    do {
40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkScalar    length = meas.getLength();
41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
426c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.org        if (fSegLength * (2 + doFill) > length) {
43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            meas.getSegment(0, length, dst, true);  // to short for us to mangle
446c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.org        } else {
45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int         n = SkScalarRound(SkScalarDiv(length, fSegLength));
46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkScalar    delta = length / n;
47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkScalar    distance = 0;
48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
496c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.org            if (meas.isClosed()) {
50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                n -= 1;
51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                distance += delta/2;
52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
53935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
54cdf1e2c68ac50376dd9ae6f335632d005182b4f7reed@google.com            if (meas.getPosTan(distance, &p, &v)) {
55cdf1e2c68ac50376dd9ae6f335632d005182b4f7reed@google.com                Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
56cdf1e2c68ac50376dd9ae6f335632d005182b4f7reed@google.com                dst->moveTo(p);
57cdf1e2c68ac50376dd9ae6f335632d005182b4f7reed@google.com            }
586c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.org            while (--n >= 0) {
59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                distance += delta;
60cdf1e2c68ac50376dd9ae6f335632d005182b4f7reed@google.com                if (meas.getPosTan(distance, &p, &v)) {
61cdf1e2c68ac50376dd9ae6f335632d005182b4f7reed@google.com                    Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
62cdf1e2c68ac50376dd9ae6f335632d005182b4f7reed@google.com                    dst->lineTo(p);
63cdf1e2c68ac50376dd9ae6f335632d005182b4f7reed@google.com                }
64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
656c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.org            if (meas.isClosed()) {
66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                dst->close();
676c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.org            }
68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    } while (meas.nextContour());
70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return true;
71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
73cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.comvoid SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
74cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.com    this->INHERITED::flatten(buffer);
75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    buffer.writeScalar(fSegLength);
76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    buffer.writeScalar(fPerterb);
77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
796c8459aa6c4bbc6e0638edab09f035924f31eda3mike@reedtribe.orgSkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) {
80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fSegLength = buffer.readScalar();
81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPerterb = buffer.readScalar();
82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
83