11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDiscretePathEffect.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBuffer.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathMeasure.h"
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRandom.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkVector normal = tangent;
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    normal.rotateCCW();
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    normal.setLength(scale);
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *p += normal;
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    : fSegLength(segLength), fPerterb(deviation)
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
2935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                                      SkScalar* width) {
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool doFill = *width < 0;
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPathMeasure   meas(src, doFill);
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t        seed = SkScalarRound(meas.getLength());
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRandom        rand(seed ^ ((seed << 16) | (seed >> 16)));
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        scale = fPerterb;
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPoint         p;
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkVector        v;
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar    length = meas.getLength();
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (fSegLength * (2 + doFill) > length) {
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            meas.getSegment(0, length, dst, true);  // to short for us to mangle
4435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        } else {
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int         n = SkScalarRound(SkScalarDiv(length, fSegLength));
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkScalar    delta = length / n;
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkScalar    distance = 0;
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            if (meas.isClosed()) {
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                n -= 1;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                distance += delta/2;
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            meas.getPosTan(distance, &p, &v);
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dst->moveTo(p);
5635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            while (--n >= 0) {
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                distance += delta;
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                meas.getPosTan(distance, &p, &v);
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dst->lineTo(p);
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            if (meas.isClosed()) {
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dst->close();
6435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            }
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (meas.nextContour());
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek SollenbergerSkFlattenable::Factory SkDiscretePathEffect::getFactory() {
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return CreateProc;
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek SollenbergerSkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) {
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkNEW_ARGS(SkDiscretePathEffect, (buffer));
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeScalar(fSegLength);
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeScalar(fPerterb);
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek SollenbergerSkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) {
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fSegLength = buffer.readScalar();
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPerterb = buffer.readScalar();
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
901cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSK_DEFINE_FLATTENABLE_REGISTRAR(SkDiscretePathEffect)
911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
92