Home | History | Annotate | Download | only in effects
      1 /* libs/graphics/effects/SkDiscretePathEffect.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkDiscretePathEffect.h"
     19 #include "SkBuffer.h"
     20 #include "SkPathMeasure.h"
     21 #include "SkRandom.h"
     22 
     23 static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale)
     24 {
     25     SkVector normal = tangent;
     26     normal.rotateCCW();
     27     normal.setLength(scale);
     28     *p += normal;
     29 }
     30 
     31 
     32 SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
     33     : fSegLength(segLength), fPerterb(deviation)
     34 {
     35 }
     36 
     37 bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
     38 {
     39     bool doFill = *width < 0;
     40 
     41     SkPathMeasure   meas(src, doFill);
     42     uint32_t        seed = SkScalarRound(meas.getLength());
     43     SkRandom        rand(seed ^ ((seed << 16) | (seed >> 16)));
     44     SkScalar        scale = fPerterb;
     45     SkPoint         p;
     46     SkVector        v;
     47 
     48     do {
     49         SkScalar    length = meas.getLength();
     50 
     51         if (fSegLength * (2 + doFill) > length)
     52         {
     53             meas.getSegment(0, length, dst, true);  // to short for us to mangle
     54         }
     55         else
     56         {
     57             int         n = SkScalarRound(SkScalarDiv(length, fSegLength));
     58             SkScalar    delta = length / n;
     59             SkScalar    distance = 0;
     60 
     61             if (meas.isClosed())
     62             {
     63                 n -= 1;
     64                 distance += delta/2;
     65             }
     66             meas.getPosTan(distance, &p, &v);
     67             Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
     68             dst->moveTo(p);
     69             while (--n >= 0)
     70             {
     71                 distance += delta;
     72                 meas.getPosTan(distance, &p, &v);
     73                 Perterb(&p, v, SkScalarMul(rand.nextSScalar1(), scale));
     74                 dst->lineTo(p);
     75             }
     76             if (meas.isClosed())
     77                 dst->close();
     78         }
     79     } while (meas.nextContour());
     80     return true;
     81 }
     82 
     83 SkFlattenable::Factory SkDiscretePathEffect::getFactory()
     84 {
     85     return CreateProc;
     86 }
     87 
     88 SkFlattenable* SkDiscretePathEffect::CreateProc(SkFlattenableReadBuffer& buffer)
     89 {
     90     return SkNEW_ARGS(SkDiscretePathEffect, (buffer));
     91 }
     92 
     93 void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer)
     94 {
     95     buffer.writeScalar(fSegLength);
     96     buffer.writeScalar(fPerterb);
     97 }
     98 
     99 SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer)
    100 {
    101     fSegLength = buffer.readScalar();
    102     fPerterb = buffer.readScalar();
    103 }
    104 
    105 
    106