Flutter Engine
The Flutter Engine
SkDiscretePathEffect.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
13#include "include/core/SkRect.h"
25
26#include <algorithm>
27#include <cstdint>
28
29class SkMatrix;
30
31/** \class LCGRandom
32
33 Utility class that implements pseudo random 32bit numbers using a fast
34 linear equation. Unlike rand(), this class holds its own seed (initially
35 set to 0), so that multiple instances can be used with no side-effects.
36
37 Copied from the original implementation of SkRandom. Only contains the
38 methods used by SkDiscretePathEffect::filterPath, with methods that were
39 not called directly moved to private.
40*/
41class LCGRandom {
42public:
43 LCGRandom(uint32_t seed) : fSeed(seed) {}
44
45 /** Return the next pseudo random number expressed as a SkScalar
46 in the range [-SK_Scalar1..SK_Scalar1).
47 */
48 SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }
49
50private:
51 /** Return the next pseudo random number as an unsigned 32bit value.
52 */
53 uint32_t nextU() { uint32_t r = fSeed * kMul + kAdd; fSeed = r; return r; }
54
55 /** Return the next pseudo random number as a signed 32bit value.
56 */
57 int32_t nextS() { return (int32_t)this->nextU(); }
58
59 /** Return the next pseudo random number expressed as a signed SkFixed
60 in the range [-SK_Fixed1..SK_Fixed1).
61 */
62 SkFixed nextSFixed1() { return this->nextS() >> 15; }
63
64 // See "Numerical Recipes in C", 1992 page 284 for these constants
65 enum {
66 kMul = 1664525,
67 kAdd = 1013904223
68 };
69 uint32_t fSeed;
70};
71
72static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
73 SkVector normal = tangent;
75 normal.setLength(scale);
76 *p += normal;
77}
78
80public:
81 SkDiscretePathEffectImpl(SkScalar segLength, SkScalar deviation, uint32_t seedAssist)
82 : fSegLength(segLength), fPerterb(deviation), fSeedAssist(seedAssist)
83 {
84 SkASSERT(SkIsFinite(segLength));
85 SkASSERT(SkIsFinite(deviation));
86 SkASSERT(segLength > SK_ScalarNearlyZero);
87 }
88
90 const SkRect*, const SkMatrix&) const override {
91 bool doFill = rec->isFillStyle();
92
93 SkPathMeasure meas(src, doFill);
94
95 /* Caller may supply their own seed assist, which by default is 0 */
96 uint32_t seed = fSeedAssist ^ SkScalarRoundToInt(meas.getLength());
97
98 LCGRandom rand(seed ^ ((seed << 16) | (seed >> 16)));
99 SkScalar scale = fPerterb;
100 SkPoint p;
101 SkVector v;
102
103 do {
104 SkScalar length = meas.getLength();
105 #if defined(SK_BUILD_FOR_FUZZER)
106 if (length > 1000) {
107 return false;
108 }
109 #endif
110
111 if (fSegLength * (2 + doFill) > length) {
112 meas.getSegment(0, length, dst, true); // to short for us to mangle
113 } else {
114 int n = SkScalarRoundToInt(length / fSegLength);
115 constexpr int kMaxReasonableIterations = 100000;
116 n = std::min(n, kMaxReasonableIterations);
117 SkScalar delta = length / n;
118 SkScalar distance = 0;
119
120 if (meas.isClosed()) {
121 n -= 1;
122 distance += delta/2;
123 }
124
125 if (meas.getPosTan(distance, &p, &v)) {
126 Perterb(&p, v, rand.nextSScalar1() * scale);
127 dst->moveTo(p);
128 }
129 while (--n >= 0) {
130 distance += delta;
131 if (meas.getPosTan(distance, &p, &v)) {
132 Perterb(&p, v, rand.nextSScalar1() * scale);
133 dst->lineTo(p);
134 }
135 }
136 if (meas.isClosed()) {
137 dst->close();
138 }
139 }
140 } while (meas.nextContour());
141 return true;
142 }
143
144 bool computeFastBounds(SkRect* bounds) const override {
145 if (bounds) {
146 SkScalar maxOutset = SkScalarAbs(fPerterb);
147 bounds->outset(maxOutset, maxOutset);
148 }
149 return true;
150 }
151
153 SkScalar segLength = buffer.readScalar();
154 SkScalar perterb = buffer.readScalar();
155 uint32_t seed = buffer.readUInt();
156 return SkDiscretePathEffect::Make(segLength, perterb, seed);
157 }
158
159 void flatten(SkWriteBuffer& buffer) const override {
160 buffer.writeScalar(fSegLength);
161 buffer.writeScalar(fPerterb);
162 buffer.writeUInt(fSeedAssist);
163 }
164
165 Factory getFactory() const override { return CreateProc; }
166 const char* getTypeName() const override { return "SkDiscretePathEffect"; }
167
168private:
169 const SkScalar fSegLength,
170 fPerterb;
171 /* Caller-supplied 32 bit seed assist */
172 const uint32_t fSeedAssist;
173
174 using INHERITED = SkPathEffectBase;
175};
176
177//////////////////////////////////////////////////////////////////////////////////////////////////
178
180 uint32_t seedAssist) {
181 if (!SkIsFinite(segLength, deviation)) {
182 return nullptr;
183 }
184 if (segLength <= SK_ScalarNearlyZero) {
185 return nullptr;
186 }
187 return sk_sp<SkPathEffect>(new SkDiscretePathEffectImpl(segLength, deviation, seedAssist));
188}
189
192}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static void Perterb(SkPoint *p, const SkVector &tangent, SkScalar scale)
int32_t SkFixed
Definition: SkFixed.h:25
#define SkFixedToScalar(x)
Definition: SkFixed.h:124
static bool SkIsFinite(T x, Pack... values)
#define SkScalarRoundToInt(x)
Definition: SkScalar.h:37
#define SK_ScalarNearlyZero
Definition: SkScalar.h:99
#define SkScalarAbs(x)
Definition: SkScalar.h:39
SkScalar nextSScalar1()
LCGRandom(uint32_t seed)
void flatten(SkWriteBuffer &buffer) const override
static sk_sp< SkFlattenable > CreateProc(SkReadBuffer &buffer)
bool onFilterPath(SkPath *dst, const SkPath &src, SkStrokeRec *rec, const SkRect *, const SkMatrix &) const override
const char * getTypeName() const override
Factory getFactory() const override
SkDiscretePathEffectImpl(SkScalar segLength, SkScalar deviation, uint32_t seedAssist)
bool computeFastBounds(SkRect *bounds) const override
static sk_sp< SkPathEffect > Make(SkScalar segLength, SkScalar dev, uint32_t seedAssist=0)
sk_sp< SkFlattenable >(* Factory)(SkReadBuffer &)
Definition: SkFlattenable.h:41
static void Register(const char name[], Factory)
SkScalar getLength()
bool getSegment(SkScalar startD, SkScalar stopD, SkPath *dst, bool startWithMoveTo)
bool getPosTan(SkScalar distance, SkPoint *position, SkVector *tangent)
Definition: SkPath.h:59
static void RotateCCW(const SkPoint &src, SkPoint *dst)
Definition: SkPointPriv.h:72
bool isFillStyle() const
Definition: SkStrokeRec.h:51
float SkScalar
Definition: extension.cpp:12
static float min(float r, float g, float b)
Definition: hsl.cpp:48
size_t length
Optional< SkRect > bounds
Definition: SkRecords.h:189
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
dst
Definition: cp.py:12
const Scalar scale