20#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
35 if ((*pathRef)->unique()) {
36 (*pathRef)->incReserve(incReserveVerbs, incReservePoints, incReserveConics);
41 if (!(*pathRef)->isInitialEmptyPathRef()) {
43 copy->copy(**
pathRef, incReserveVerbs, incReservePoints, incReserveConics);
48 copy =
new SkPathRef(incReserveVerbs, incReservePoints, incReserveConics);
53 fPathRef->callGenIDChangeListeners();
54 fPathRef->fGenerationID = 0;
55 fPathRef->fBoundsIsDirty =
true;
63 + fPoints .capacity() *
sizeof(fPoints [0])
64 + fVerbs .capacity() *
sizeof(fVerbs [0])
65 + fConicWeights.
capacity() *
sizeof(fConicWeights[0]);
121 if (sameSign != antiDiag) {
124 *
start = (inStart + 4 - (topNeg | antiDiag)) % 4;
133 *
start = (6 + (topNeg | antiDiag) - inStart) % 4;
145 if (
matrix.isIdentity()) {
155 if (!(*dst)->unique()) {
166 (*dst)->fVerbs =
src.fVerbs;
167 (*dst)->fConicWeights =
src.fConicWeights;
168 (*dst)->callGenIDChangeListeners();
169 (*dst)->fGenerationID = 0;
171 (*dst)->fPoints.resize(
src.fPoints.size());
173 matrix.mapPoints((*dst)->fPoints.begin(),
src.fPoints.begin(),
src.fPoints.size());
176 bool canXformBounds = !
src.fBoundsIsDirty &&
matrix.rectStaysRect() &&
src.countPoints() > 1;
188 if (canXformBounds) {
189 (*dst)->fBoundsIsDirty =
false;
191 matrix.mapRect(&(*dst)->fBounds,
src.fBounds);
192 if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) {
193 (*dst)->fBounds.setEmpty();
196 (*dst)->fIsFinite =
false;
197 (*dst)->fBounds.setEmpty();
200 (*dst)->fBoundsIsDirty =
true;
203 (*dst)->fSegmentMask =
src.fSegmentMask;
208 bool rectStaysRect =
matrix.rectStaysRect();
211 (*dst)->fType = newType;
214 unsigned start =
src.fRRectOrOvalStartIdx;
217 (*dst)->fRRectOrOvalIsCCW = isCCW;
218 (*dst)->fRRectOrOvalStartIdx =
start;
222 (*dst)->callGenIDChangeListeners();
223 (*dst)->fGenerationID = 0;
230 if ((*pathRef)->unique()) {
232 (*pathRef)->callGenIDChangeListeners();
233 (*pathRef)->fBoundsIsDirty =
true;
234 (*pathRef)->fGenerationID = 0;
235 (*pathRef)->fPoints.clear();
236 (*pathRef)->fVerbs.clear();
237 (*pathRef)->fConicWeights.clear();
238 (*pathRef)->fSegmentMask = 0;
242 int oldVCnt = (*pathRef)->countVerbs();
243 int oldPCnt = (*pathRef)->countPoints();
245 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt);
256 if (fSegmentMask !=
ref.fSegmentMask) {
260 bool genIDMatch = fGenerationID && fGenerationID ==
ref.fGenerationID;
266 if (fPoints !=
ref.fPoints || fConicWeights !=
ref.fConicWeights || fVerbs !=
ref.fVerbs) {
270 if (
ref.fVerbs.empty()) {
277 int additionalReserveVerbs,
278 int additionalReservePoints,
279 int additionalReserveConics) {
281 this->resetToSize(
ref.fVerbs.size(),
ref.fPoints.size(),
ref.fConicWeights.size(),
282 additionalReserveVerbs, additionalReservePoints, additionalReserveConics);
284 fPoints =
ref.fPoints;
285 fConicWeights =
ref.fConicWeights;
286 fBoundsIsDirty =
ref.fBoundsIsDirty;
287 if (!fBoundsIsDirty) {
288 fBounds =
ref.fBounds;
289 fIsFinite =
ref.fIsFinite;
291 fSegmentMask =
ref.fSegmentMask;
293 fRRectOrOvalIsCCW =
ref.fRRectOrOvalIsCCW;
294 fRRectOrOvalStartIdx =
ref.fRRectOrOvalStartIdx;
295 fArcOval =
ref.fArcOval;
296 fArcStartAngle =
ref.fArcStartAngle;
297 fArcSweepAngle =
ref.fArcSweepAngle;
298 fArcType =
ref.fArcType;
303 const SkScalar* inValues = &ending.getPoints()->
fX;
304 SkScalar* outValues = &
out->getWritablePoints()->fX;
306 for (
int index = 0; index <
count; ++index) {
307 outValues[index] = outValues[index] * weight + inValues[index] * (1 - weight);
309 out->fBoundsIsDirty =
true;
313std::tuple<SkPoint*, SkScalar*> SkPathRef::growForVerbsInPath(
const SkPathRef&
path) {
316 fSegmentMask |=
path.fSegmentMask;
317 fBoundsIsDirty =
true;
320 if (
int numVerbs =
path.countVerbs()) {
321 memcpy(fVerbs.
push_back_n(numVerbs),
path.fVerbs.begin(), numVerbs *
sizeof(fVerbs[0]));
325 if (
int numPts =
path.countPoints()) {
330 if (
int numConics =
path.countWeights()) {
335 return {pts, weights};
338SkPoint* SkPathRef::growForRepeatedVerb(
int verb,
364 SkDEBUGFAIL(
"growForRepeatedVerb called for kClose_Verb");
368 SkDEBUGFAIL(
"growForRepeatedVerb called for kDone");
377 fBoundsIsDirty =
true;
428 fSegmentMask |= mask;
429 fBoundsIsDirty =
true;
447 SkASSERT(fEditorsAttached.load() == 0);
450 if (fGenerationID == 0) {
452 fGenerationID = kEmptyGenID;
454 static std::atomic<uint32_t> nextID{kEmptyGenID + 1};
456 fGenerationID = nextID.fetch_add(1, std::memory_order_relaxed) &
kMask;
457 }
while (fGenerationID == 0 || fGenerationID == kEmptyGenID);
460 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
464 return fGenerationID;
471 fGenIDChangeListeners.
add(std::move(listener));
477void SkPathRef::callGenIDChangeListeners() {
478 fGenIDChangeListeners.
changed();
483 SkVector radii[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
486 uint8_t verb = iter.
next(pts);
496 }
else if (!v1_0.
fY) {
504 pts[1].fX ==
bounds.fLeft ?
505 pts[1].fY ==
bounds.fTop ?
507 pts[1].fY ==
bounds.fTop ?
509 SkASSERT(!radii[corner].fX && !radii[corner].fY);
510 radii[corner] = dxdy;
513 && (!(pts[1].fX - pts[0].fX) || !(pts[1].fY - pts[0].fY)))
528 *isCCW =
SkToBool(fRRectOrOvalIsCCW);
531 *
start = fRRectOrOvalStartIdx;
542 fConicWeights =
nullptr;
550 this->setPathRef(
path);
555 fVerbs =
path.verbsBegin();
556 fVerbStop =
path.verbsEnd();
557 fConicWeights =
path.conicWeights();
563 if (!
path.isFinite()) {
573 if (fVerbs == fVerbStop) {
579 unsigned verb = *fVerbs++;
616 return (uint8_t) verb;
630 if (fRRectOrOvalStartIdx >= 4) {
635 if (fRRectOrOvalStartIdx >= 8) {
646 if (!fBoundsIsDirty && !fBounds.
isEmpty()) {
650 for (
int i = 0;
i < fPoints.
size(); ++
i) {
653 if (fPoints[
i].
isFinite() && (
any(point < leftTop)||
any(point > rightBot))) {
654 SkDebugf(
"bad SkPathRef bounds: %g %g %g %g\n",
656 for (
int j = 0; j < fPoints.
size(); ++j) {
658 SkDebugf(
"*** bounds do not contain: ");
660 SkDebugf(
"%g %g\n", fPoints[j].fX, fPoints[j].fY);
666 if (fPoints[
i].
isFinite() &&
any(point < leftTop) && !
any(point > rightBot))
683 fConicWeights.
clear();
690 info.segmentMask == fSegmentMask &&
692 info.weights == fConicWeights.
size();
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
#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])
SkDEBUGCODE(void validate() const { SkASSERT(this->isValid());}) void reset()
uint32_t genID(uint8_t fillType) const
SkPathRef(SkSpan< const SkPoint > points, SkSpan< const uint8_t > verbs, SkSpan< const SkScalar > weights, unsigned segmentMask)
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)
unsigned useCenter Optional< SkMatrix > matrix
Optional< SkRect > bounds
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
SIT bool any(const Vec< 1, T > &x)
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