1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci 9cb93a386Sopenharmony_ci#include "include/core/SkPathMeasure.h" 10cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h" 11cb93a386Sopenharmony_ci#include "include/effects/SkDiscretePathEffect.h" 12cb93a386Sopenharmony_ci#include "include/private/SkFixed.h" 13cb93a386Sopenharmony_ci#include "src/core/SkPathEffectBase.h" 14cb93a386Sopenharmony_ci#include "src/core/SkPointPriv.h" 15cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h" 16cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci/** \class LCGRandom 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci Utility class that implements pseudo random 32bit numbers using a fast 21cb93a386Sopenharmony_ci linear equation. Unlike rand(), this class holds its own seed (initially 22cb93a386Sopenharmony_ci set to 0), so that multiple instances can be used with no side-effects. 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci Copied from the original implementation of SkRandom. Only contains the 25cb93a386Sopenharmony_ci methods used by SkDiscretePathEffect::filterPath, with methods that were 26cb93a386Sopenharmony_ci not called directly moved to private. 27cb93a386Sopenharmony_ci*/ 28cb93a386Sopenharmony_ciclass LCGRandom { 29cb93a386Sopenharmony_cipublic: 30cb93a386Sopenharmony_ci LCGRandom(uint32_t seed) : fSeed(seed) {} 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci /** Return the next pseudo random number expressed as a SkScalar 33cb93a386Sopenharmony_ci in the range [-SK_Scalar1..SK_Scalar1). 34cb93a386Sopenharmony_ci */ 35cb93a386Sopenharmony_ci SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); } 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciprivate: 38cb93a386Sopenharmony_ci /** Return the next pseudo random number as an unsigned 32bit value. 39cb93a386Sopenharmony_ci */ 40cb93a386Sopenharmony_ci uint32_t nextU() { uint32_t r = fSeed * kMul + kAdd; fSeed = r; return r; } 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci /** Return the next pseudo random number as a signed 32bit value. 43cb93a386Sopenharmony_ci */ 44cb93a386Sopenharmony_ci int32_t nextS() { return (int32_t)this->nextU(); } 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci /** Return the next pseudo random number expressed as a signed SkFixed 47cb93a386Sopenharmony_ci in the range [-SK_Fixed1..SK_Fixed1). 48cb93a386Sopenharmony_ci */ 49cb93a386Sopenharmony_ci SkFixed nextSFixed1() { return this->nextS() >> 15; } 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci // See "Numerical Recipes in C", 1992 page 284 for these constants 52cb93a386Sopenharmony_ci enum { 53cb93a386Sopenharmony_ci kMul = 1664525, 54cb93a386Sopenharmony_ci kAdd = 1013904223 55cb93a386Sopenharmony_ci }; 56cb93a386Sopenharmony_ci uint32_t fSeed; 57cb93a386Sopenharmony_ci}; 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_cistatic void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) { 60cb93a386Sopenharmony_ci SkVector normal = tangent; 61cb93a386Sopenharmony_ci SkPointPriv::RotateCCW(&normal); 62cb93a386Sopenharmony_ci normal.setLength(scale); 63cb93a386Sopenharmony_ci *p += normal; 64cb93a386Sopenharmony_ci} 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ciclass SK_API SkDiscretePathEffectImpl : public SkPathEffectBase { 67cb93a386Sopenharmony_cipublic: 68cb93a386Sopenharmony_ci SkDiscretePathEffectImpl(SkScalar segLength, SkScalar deviation, uint32_t seedAssist) 69cb93a386Sopenharmony_ci : fSegLength(segLength), fPerterb(deviation), fSeedAssist(seedAssist) 70cb93a386Sopenharmony_ci { 71cb93a386Sopenharmony_ci SkASSERT(SkScalarIsFinite(segLength)); 72cb93a386Sopenharmony_ci SkASSERT(SkScalarIsFinite(deviation)); 73cb93a386Sopenharmony_ci SkASSERT(segLength > SK_ScalarNearlyZero); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, 77cb93a386Sopenharmony_ci const SkRect*, const SkMatrix&) const override { 78cb93a386Sopenharmony_ci bool doFill = rec->isFillStyle(); 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci SkPathMeasure meas(src, doFill); 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci /* Caller may supply their own seed assist, which by default is 0 */ 83cb93a386Sopenharmony_ci uint32_t seed = fSeedAssist ^ SkScalarRoundToInt(meas.getLength()); 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci LCGRandom rand(seed ^ ((seed << 16) | (seed >> 16))); 86cb93a386Sopenharmony_ci SkScalar scale = fPerterb; 87cb93a386Sopenharmony_ci SkPoint p; 88cb93a386Sopenharmony_ci SkVector v; 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci do { 91cb93a386Sopenharmony_ci SkScalar length = meas.getLength(); 92cb93a386Sopenharmony_ci #if defined(SK_BUILD_FOR_FUZZER) 93cb93a386Sopenharmony_ci if (length > 1000) { 94cb93a386Sopenharmony_ci return false; 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci #endif 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci if (fSegLength * (2 + doFill) > length) { 99cb93a386Sopenharmony_ci meas.getSegment(0, length, dst, true); // to short for us to mangle 100cb93a386Sopenharmony_ci } else { 101cb93a386Sopenharmony_ci int n = SkScalarRoundToInt(length / fSegLength); 102cb93a386Sopenharmony_ci constexpr int kMaxReasonableIterations = 100000; 103cb93a386Sopenharmony_ci n = std::min(n, kMaxReasonableIterations); 104cb93a386Sopenharmony_ci SkScalar delta = length / n; 105cb93a386Sopenharmony_ci SkScalar distance = 0; 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci if (meas.isClosed()) { 108cb93a386Sopenharmony_ci n -= 1; 109cb93a386Sopenharmony_ci distance += delta/2; 110cb93a386Sopenharmony_ci } 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci if (meas.getPosTan(distance, &p, &v)) { 113cb93a386Sopenharmony_ci Perterb(&p, v, rand.nextSScalar1() * scale); 114cb93a386Sopenharmony_ci dst->moveTo(p); 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci while (--n >= 0) { 117cb93a386Sopenharmony_ci distance += delta; 118cb93a386Sopenharmony_ci if (meas.getPosTan(distance, &p, &v)) { 119cb93a386Sopenharmony_ci Perterb(&p, v, rand.nextSScalar1() * scale); 120cb93a386Sopenharmony_ci dst->lineTo(p); 121cb93a386Sopenharmony_ci } 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci if (meas.isClosed()) { 124cb93a386Sopenharmony_ci dst->close(); 125cb93a386Sopenharmony_ci } 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci } while (meas.nextContour()); 128cb93a386Sopenharmony_ci return true; 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci bool computeFastBounds(SkRect* bounds) const override { 132cb93a386Sopenharmony_ci if (bounds) { 133cb93a386Sopenharmony_ci SkScalar maxOutset = SkScalarAbs(fPerterb); 134cb93a386Sopenharmony_ci bounds->outset(maxOutset, maxOutset); 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci return true; 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) { 140cb93a386Sopenharmony_ci SkScalar segLength = buffer.readScalar(); 141cb93a386Sopenharmony_ci SkScalar perterb = buffer.readScalar(); 142cb93a386Sopenharmony_ci uint32_t seed = buffer.readUInt(); 143cb93a386Sopenharmony_ci return SkDiscretePathEffect::Make(segLength, perterb, seed); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci void flatten(SkWriteBuffer& buffer) const override { 147cb93a386Sopenharmony_ci buffer.writeScalar(fSegLength); 148cb93a386Sopenharmony_ci buffer.writeScalar(fPerterb); 149cb93a386Sopenharmony_ci buffer.writeUInt(fSeedAssist); 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci Factory getFactory() const override { return CreateProc; } 153cb93a386Sopenharmony_ci const char* getTypeName() const override { return "SkDiscretePathEffect"; } 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ciprivate: 156cb93a386Sopenharmony_ci const SkScalar fSegLength, 157cb93a386Sopenharmony_ci fPerterb; 158cb93a386Sopenharmony_ci /* Caller-supplied 32 bit seed assist */ 159cb93a386Sopenharmony_ci const uint32_t fSeedAssist; 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci using INHERITED = SkPathEffectBase; 162cb93a386Sopenharmony_ci}; 163cb93a386Sopenharmony_ci 164cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkDiscretePathEffect::Make(SkScalar segLength, SkScalar deviation, 167cb93a386Sopenharmony_ci uint32_t seedAssist) { 168cb93a386Sopenharmony_ci if (!SkScalarIsFinite(segLength) || !SkScalarIsFinite(deviation)) { 169cb93a386Sopenharmony_ci return nullptr; 170cb93a386Sopenharmony_ci } 171cb93a386Sopenharmony_ci if (segLength <= SK_ScalarNearlyZero) { 172cb93a386Sopenharmony_ci return nullptr; 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci return sk_sp<SkPathEffect>(new SkDiscretePathEffectImpl(segLength, deviation, seedAssist)); 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_civoid SkDiscretePathEffect::RegisterFlattenables() { 178cb93a386Sopenharmony_ci SkFlattenable::Register("SkDiscretePathEffect", SkDiscretePathEffectImpl::CreateProc); 179cb93a386Sopenharmony_ci} 180