19#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
34 if ((*pathRef)->unique()) {
35 (*pathRef)->incReserve(incReserveVerbs, incReservePoints, incReserveConics);
40 if (!(*pathRef)->isInitialEmptyPathRef()) {
42 copy->copy(**
pathRef, incReserveVerbs, incReservePoints, incReserveConics);
47 copy =
new SkPathRef(incReserveVerbs, incReservePoints, incReserveConics);
52 fPathRef->callGenIDChangeListeners();
53 fPathRef->fGenerationID = 0;
54 fPathRef->fBoundsIsDirty =
true;
62 + fPoints .capacity() *
sizeof(fPoints [0])
63 + fVerbs .capacity() *
sizeof(fVerbs [0])
64 + fConicWeights.
capacity() *
sizeof(fConicWeights[0]);
120 if (sameSign != antiDiag) {
123 *
start = (inStart + 4 - (topNeg | antiDiag)) % 4;
132 *
start = (6 + (topNeg | antiDiag) - inStart) % 4;
144 if (matrix.isIdentity()) {
145 if (dst->get() != &src) {
147 dst->reset(
const_cast<SkPathRef*
>(&src));
154 if (!(*dst)->unique()) {
158 if (dst->get() == &src) {
164 if (dst->get() != &src) {
165 (*dst)->fVerbs = src.fVerbs;
166 (*dst)->fConicWeights = src.fConicWeights;
167 (*dst)->callGenIDChangeListeners();
168 (*dst)->fGenerationID = 0;
170 (*dst)->fPoints.resize(src.fPoints.size());
172 matrix.mapPoints((*dst)->fPoints.begin(), src.fPoints.begin(), src.fPoints.size());
175 bool canXformBounds = !src.fBoundsIsDirty && matrix.rectStaysRect() && src.countPoints() > 1;
187 if (canXformBounds) {
188 (*dst)->fBoundsIsDirty =
false;
190 matrix.mapRect(&(*dst)->fBounds, src.fBounds);
191 if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) {
192 (*dst)->fBounds.setEmpty();
195 (*dst)->fIsFinite =
false;
196 (*dst)->fBounds.setEmpty();
199 (*dst)->fBoundsIsDirty =
true;
202 (*dst)->fSegmentMask = src.fSegmentMask;
207 bool rectStaysRect = matrix.rectStaysRect();
210 (*dst)->fType = newType;
212 unsigned start = src.fRRectOrOvalStartIdx;
213 bool isCCW =
SkToBool(src.fRRectOrOvalIsCCW);
215 (*dst)->fRRectOrOvalIsCCW = isCCW;
216 (*dst)->fRRectOrOvalStartIdx =
start;
219 if (dst->get() == &src) {
220 (*dst)->callGenIDChangeListeners();
221 (*dst)->fGenerationID = 0;
228 if ((*pathRef)->unique()) {
230 (*pathRef)->callGenIDChangeListeners();
231 (*pathRef)->fBoundsIsDirty =
true;
232 (*pathRef)->fGenerationID = 0;
233 (*pathRef)->fPoints.clear();
234 (*pathRef)->fVerbs.clear();
235 (*pathRef)->fConicWeights.clear();
236 (*pathRef)->fSegmentMask = 0;
240 int oldVCnt = (*pathRef)->countVerbs();
241 int oldPCnt = (*pathRef)->countPoints();
243 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt);
254 if (fSegmentMask !=
ref.fSegmentMask) {
258 bool genIDMatch = fGenerationID && fGenerationID ==
ref.fGenerationID;
264 if (fPoints !=
ref.fPoints || fConicWeights !=
ref.fConicWeights || fVerbs !=
ref.fVerbs) {
268 if (
ref.fVerbs.empty()) {
275 int additionalReserveVerbs,
276 int additionalReservePoints,
277 int additionalReserveConics) {
279 this->resetToSize(
ref.fVerbs.size(),
ref.fPoints.size(),
ref.fConicWeights.size(),
280 additionalReserveVerbs, additionalReservePoints, additionalReserveConics);
282 fPoints =
ref.fPoints;
283 fConicWeights =
ref.fConicWeights;
284 fBoundsIsDirty =
ref.fBoundsIsDirty;
285 if (!fBoundsIsDirty) {
286 fBounds =
ref.fBounds;
287 fIsFinite =
ref.fIsFinite;
289 fSegmentMask =
ref.fSegmentMask;
291 fRRectOrOvalIsCCW =
ref.fRRectOrOvalIsCCW;
292 fRRectOrOvalStartIdx =
ref.fRRectOrOvalStartIdx;
293 fArcOval =
ref.fArcOval;
294 fArcStartAngle =
ref.fArcStartAngle;
295 fArcSweepAngle =
ref.fArcSweepAngle;
296 fArcUseCenter =
ref.fArcUseCenter;
301 const SkScalar* inValues = &ending.getPoints()->
fX;
302 SkScalar* outValues = &out->getWritablePoints()->fX;
303 int count = out->countPoints() * 2;
304 for (
int index = 0; index <
count; ++index) {
305 outValues[index] = outValues[index] * weight + inValues[index] * (1 - weight);
307 out->fBoundsIsDirty =
true;
311std::tuple<SkPoint*, SkScalar*> SkPathRef::growForVerbsInPath(
const SkPathRef& path) {
314 fSegmentMask |= path.fSegmentMask;
315 fBoundsIsDirty =
true;
318 if (
int numVerbs = path.countVerbs()) {
319 memcpy(fVerbs.
push_back_n(numVerbs), path.fVerbs.begin(), numVerbs *
sizeof(fVerbs[0]));
323 if (
int numPts =
path.countPoints()) {
328 if (
int numConics =
path.countWeights()) {
333 return {pts, weights};
336SkPoint* SkPathRef::growForRepeatedVerb(
int verb,
362 SkDEBUGFAIL(
"growForRepeatedVerb called for kClose_Verb");
366 SkDEBUGFAIL(
"growForRepeatedVerb called for kDone");
375 fBoundsIsDirty =
true;
426 fSegmentMask |= mask;
427 fBoundsIsDirty =
true;
441 SkASSERT(fEditorsAttached.load() == 0);
444 if (fGenerationID == 0) {
446 fGenerationID = kEmptyGenID;
448 static std::atomic<uint32_t> nextID{kEmptyGenID + 1};
450 fGenerationID = nextID.fetch_add(1, std::memory_order_relaxed) &
kMask;
451 }
while (fGenerationID == 0 || fGenerationID == kEmptyGenID);
454 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
458 return fGenerationID;
465 fGenIDChangeListeners.
add(std::move(listener));
471void SkPathRef::callGenIDChangeListeners() {
472 fGenIDChangeListeners.
changed();
477 SkVector radii[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
480 uint8_t verb = iter.
next(pts);
490 }
else if (!v1_0.
fY) {
498 pts[1].fX == bounds.fLeft ?
499 pts[1].fY == bounds.fTop ?
501 pts[1].fY == bounds.fTop ?
503 SkASSERT(!radii[corner].fX && !radii[corner].fY);
504 radii[corner] = dxdy;
507 && (!(pts[1].fX - pts[0].fX) || !(pts[1].fY - pts[0].fY)))
522 *isCCW =
SkToBool(fRRectOrOvalIsCCW);
525 *
start = fRRectOrOvalStartIdx;
536 fConicWeights =
nullptr;
544 this->setPathRef(path);
548 fPts = path.points();
549 fVerbs = path.verbsBegin();
550 fVerbStop = path.verbsEnd();
551 fConicWeights = path.conicWeights();
557 if (!path.isFinite()) {
567 if (fVerbs == fVerbStop) {
573 unsigned verb = *fVerbs++;
610 return (uint8_t) verb;
623 if (fRRectOrOvalStartIdx >= 4) {
628 if (fRRectOrOvalStartIdx >= 8) {
639 if (!fBoundsIsDirty && !fBounds.
isEmpty()) {
643 for (
int i = 0; i < fPoints.
size(); ++i) {
644 auto point =
skvx::float2(fPoints[i].fX, fPoints[i].fY);
646 if (fPoints[i].
isFinite() && (any(point < leftTop)|| any(point > rightBot))) {
647 SkDebugf(
"bad SkPathRef bounds: %g %g %g %g\n",
649 for (
int j = 0; j < fPoints.
size(); ++j) {
651 SkDebugf(
"*** bounds do not contain: ");
653 SkDebugf(
"%g %g\n", fPoints[j].fX, fPoints[j].fY);
659 if (fPoints[i].
isFinite() && any(point < leftTop) && !any(point > rightBot))
672void SkPathRef::reset() {
676 fConicWeights.
clear();
683 info.segmentMask == fSegmentMask &&
685 info.weights == fConicWeights.
size();
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static constexpr uint64_t kMask
#define SkDEBUGFAIL(message)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool SkIsFinite(T x, Pack... values)
static constexpr int kPathRefGenIDBitCnt
static void transform_dir_and_start(const SkMatrix &matrix, bool isRRect, bool *isCCW, unsigned *start)
static SkPathRef * gEmpty
SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t verbs[], int count)
static constexpr bool SkToBool(const T &x)
void changed() SK_EXCLUDES(fMutex)
int count() const SK_EXCLUDES(fMutex)
void add(sk_sp< SkIDChangeListener > listener) SK_EXCLUDES(fMutex)
static constexpr int kMScaleX
horizontal scale factor
static constexpr int kMSkewY
vertical skew factor
static constexpr int kMScaleY
vertical scale factor
static constexpr int kMSkewX
horizontal skew factor
Editor(sk_sp< SkPathRef > *pathRef, int incReserveVerbs=0, int incReservePoints=0, int incReserveConics=0)
void setPathRef(const SkPathRef &)
uint8_t next(SkPoint pts[4])
uint32_t genID(uint8_t fillType) const
bool operator==(const SkPathRef &ref) const
const SkRect & getBounds() const
int genIDChangeListenerCount()
static void Rewind(sk_sp< SkPathRef > *pathRef)
static void CreateTransformedCopy(sk_sp< SkPathRef > *dst, const SkPathRef &src, const SkMatrix &matrix)
static SkPathRef * CreateEmpty()
size_t approximateBytesUsed() const
bool isRRect(SkRRect *rrect, bool *isCCW, unsigned *start) const
bool dataMatchesVerbs() const
void addGenIDChangeListener(sk_sp< SkIDChangeListener >)
void interpolate(const SkPathRef &ending, SkScalar weight, SkPathRef *out) const
@ kUpperLeft_Corner
index of top-left corner radii
@ kLowerRight_Corner
index of bottom-right corner radii
@ kUpperRight_Corner
index of top-right corner radii
@ kLowerLeft_Corner
index of bottom-left corner radii
void setRectRadii(const SkRect &rect, const SkVector radii[4])
void reset(T *ptr=nullptr)
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
void set(float x, float y)
SkScalar fBottom
larger y-axis bounds
SkScalar fLeft
smaller x-axis bounds
SkScalar fRight
larger x-axis bounds
SkScalar fTop
smaller y-axis bounds