Home | History | Annotate | Download | only in effects
      1 
      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 
      9 
     10 #include "SkDiscretePathEffect.h"
     11 #include "SkBuffer.h"
     12 #include "SkPathMeasure.h"
     13 #include "SkRandom.h"
     14 
     15 static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
     16     SkVector normal = tangent;
     17     normal.rotateCCW();
     18     normal.setLength(scale);
     19     *p += normal;
     20 }
     21 
     22 
     23 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
     24     : fSegLength(segLength), fPerterb(deviation)
     25 {
     26 }
     27 
     28 bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
     29                                       SkScalar* width) {
     30     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 
     42         if (fSegLength * (2 + doFill) > length) {
     43             meas.getSegment(0, length, dst, true);  // to short for us to mangle
     44         } else {
     45             int         n = SkScalarRound(SkScalarDiv(length, fSegLength));
     46             SkScalar    delta = length / n;
     47             SkScalar    distance = 0;
     48 
     49             if (meas.isClosed()) {
     50                 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);
     56             while (--n >= 0) {
     57                 distance += delta;
     58                 meas.getPosTan(distance, &p, &v);
     59                 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
     60                 dst->lineTo(p);
     61             }
     62             if (meas.isClosed()) {
     63                 dst->close();
     64             }
     65         }
     66     } while (meas.nextContour());
     67     return true;
     68 }
     69 
     70 SkFlattenable::Factory SkDiscretePathEffect::getFactory() {
     71     return CreateProc;
     72 }
     73 
     74 SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) {
     75     return SkNEW_ARGS(SkDiscretePathEffect, (buffer));
     76 }
     77 
     78 void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
     79     buffer.writeScalar(fSegLength);
     80     buffer.writeScalar(fPerterb);
     81 }
     82 
     83 SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) {
     84     fSegLength = buffer.readScalar();
     85     fPerterb = buffer.readScalar();
     86 }
     87 
     88 ///////////////////////////////////////////////////////////////////////////////
     89 
     90 SK_DEFINE_FLATTENABLE_REGISTRAR(SkDiscretePathEffect)
     91 
     92