зеркало из https://github.com/mozilla/moz-skia.git
Move segment mask from SkPath to SkPathRef
https://codereview.chromium.org/105083003/ git-svn-id: http://skia.googlecode.com/svn/trunk@12660 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
c7a8507e97
Коммит
6b8dbb668f
|
@ -778,7 +778,7 @@ public:
|
||||||
* set if the path contains 1 or more segments of that type.
|
* set if the path contains 1 or more segments of that type.
|
||||||
* Returns 0 for an empty path (no segments).
|
* Returns 0 for an empty path (no segments).
|
||||||
*/
|
*/
|
||||||
uint32_t getSegmentMasks() const { return fSegmentMask; }
|
uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
|
||||||
|
|
||||||
enum Verb {
|
enum Verb {
|
||||||
kMove_Verb, //!< iter.next returns 1 point
|
kMove_Verb, //!< iter.next returns 1 point
|
||||||
|
@ -942,14 +942,15 @@ private:
|
||||||
#endif
|
#endif
|
||||||
kConvexity_SerializationShift = 16, // requires 8 bits
|
kConvexity_SerializationShift = 16, // requires 8 bits
|
||||||
kFillType_SerializationShift = 8, // requires 8 bits
|
kFillType_SerializationShift = 8, // requires 8 bits
|
||||||
kSegmentMask_SerializationShift = 0 // requires 4 bits
|
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
||||||
|
kOldSegmentMask_SerializationShift = 0 // requires 4 bits
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
SkAutoTUnref<SkPathRef> fPathRef;
|
SkAutoTUnref<SkPathRef> fPathRef;
|
||||||
|
|
||||||
int fLastMoveToIndex;
|
int fLastMoveToIndex;
|
||||||
uint8_t fFillType;
|
uint8_t fFillType;
|
||||||
uint8_t fSegmentMask;
|
|
||||||
mutable uint8_t fConvexity;
|
mutable uint8_t fConvexity;
|
||||||
mutable uint8_t fDirection;
|
mutable uint8_t fDirection;
|
||||||
#ifdef SK_BUILD_FOR_ANDROID
|
#ifdef SK_BUILD_FOR_ANDROID
|
||||||
|
|
|
@ -62,30 +62,24 @@ public:
|
||||||
/**
|
/**
|
||||||
* Adds the verb and allocates space for the number of points indicated by the verb. The
|
* Adds the verb and allocates space for the number of points indicated by the verb. The
|
||||||
* return value is a pointer to where the points for the verb should be written.
|
* return value is a pointer to where the points for the verb should be written.
|
||||||
|
* 'weight' is only used if 'verb' is kConic_Verb
|
||||||
*/
|
*/
|
||||||
SkPoint* growForVerb(int /*SkPath::Verb*/ verb) {
|
SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight = 0) {
|
||||||
SkDEBUGCODE(fPathRef->validate();)
|
SkDEBUGCODE(fPathRef->validate();)
|
||||||
return fPathRef->growForVerb(verb);
|
return fPathRef->growForVerb(verb, weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkPoint* growForConic(SkScalar w);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates space for additional verbs and points and returns pointers to the new verbs and
|
* Allocates space for multiple instances of a particular verb and the
|
||||||
* points. verbs will point one beyond the first new verb (index it using [~<i>]). pts points
|
* requisite points & weights.
|
||||||
* at the first new point (indexed normally [<i>]).
|
* The return pointer points at the first new point (indexed normally [<i>]).
|
||||||
|
* If 'verb' is kConic_Verb, 'weights' will return a pointer to the
|
||||||
|
* space for the conic weights (indexed normally).
|
||||||
*/
|
*/
|
||||||
void grow(int newVerbs, int newPts, uint8_t** verbs, SkPoint** pts) {
|
SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb,
|
||||||
SkASSERT(NULL != verbs);
|
int numVbs,
|
||||||
SkASSERT(NULL != pts);
|
SkScalar** weights = NULL) {
|
||||||
SkDEBUGCODE(fPathRef->validate();)
|
return fPathRef->growForRepeatedVerb(verb, numVbs, weights);
|
||||||
int oldVerbCnt = fPathRef->fVerbCnt;
|
|
||||||
int oldPointCnt = fPathRef->fPointCnt;
|
|
||||||
SkASSERT(verbs && pts);
|
|
||||||
fPathRef->grow(newVerbs, newPts);
|
|
||||||
*verbs = fPathRef->fVerbs - oldVerbCnt;
|
|
||||||
*pts = fPathRef->fPoints + oldPointCnt;
|
|
||||||
SkDEBUGCODE(fPathRef->validate();)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,6 +117,13 @@ public:
|
||||||
return SkToBool(fIsFinite);
|
return SkToBool(fIsFinite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mask, where each bit corresponding to a SegmentMask is
|
||||||
|
* set if the path contains 1 or more segments of that type.
|
||||||
|
* Returns 0 for an empty path (no segments).
|
||||||
|
*/
|
||||||
|
uint32_t getSegmentMasks() const { return fSegmentMask; }
|
||||||
|
|
||||||
/** Returns true if the path is an oval.
|
/** Returns true if the path is an oval.
|
||||||
*
|
*
|
||||||
* @param rect returns the bounding rect of this oval. It's a circle
|
* @param rect returns the bounding rect of this oval. It's a circle
|
||||||
|
@ -199,6 +200,7 @@ public:
|
||||||
|
|
||||||
int countPoints() const { SkDEBUGCODE(this->validate();) return fPointCnt; }
|
int countPoints() const { SkDEBUGCODE(this->validate();) return fPointCnt; }
|
||||||
int countVerbs() const { SkDEBUGCODE(this->validate();) return fVerbCnt; }
|
int countVerbs() const { SkDEBUGCODE(this->validate();) return fVerbCnt; }
|
||||||
|
int countWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.count(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a pointer one beyond the first logical verb (last verb in memory order).
|
* Returns a pointer one beyond the first logical verb (last verb in memory order).
|
||||||
|
@ -226,7 +228,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Convenience methods for getting to a verb or point by index.
|
* Convenience methods for getting to a verb or point by index.
|
||||||
*/
|
*/
|
||||||
uint8_t atVerb(int index) {
|
uint8_t atVerb(int index) const {
|
||||||
SkASSERT((unsigned) index < (unsigned) fVerbCnt);
|
SkASSERT((unsigned) index < (unsigned) fVerbCnt);
|
||||||
return this->verbs()[~index];
|
return this->verbs()[~index];
|
||||||
}
|
}
|
||||||
|
@ -240,12 +242,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* Writes the path points and verbs to a buffer.
|
* Writes the path points and verbs to a buffer.
|
||||||
*/
|
*/
|
||||||
void writeToBuffer(SkWBuffer* buffer);
|
void writeToBuffer(SkWBuffer* buffer) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of bytes that would be written in writeBuffer()
|
* Gets the number of bytes that would be written in writeBuffer()
|
||||||
*/
|
*/
|
||||||
uint32_t writeSize();
|
uint32_t writeSize() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the
|
* Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the
|
||||||
|
@ -258,6 +260,7 @@ private:
|
||||||
enum SerializationOffsets {
|
enum SerializationOffsets {
|
||||||
kIsFinite_SerializationShift = 25, // requires 1 bit
|
kIsFinite_SerializationShift = 25, // requires 1 bit
|
||||||
kIsOval_SerializationShift = 24, // requires 1 bit
|
kIsOval_SerializationShift = 24, // requires 1 bit
|
||||||
|
kSegmentMask_SerializationShift = 0 // requires 4 bits
|
||||||
};
|
};
|
||||||
|
|
||||||
SkPathRef() {
|
SkPathRef() {
|
||||||
|
@ -268,6 +271,7 @@ private:
|
||||||
fPoints = NULL;
|
fPoints = NULL;
|
||||||
fFreeSpace = 0;
|
fFreeSpace = 0;
|
||||||
fGenerationID = kEmptyGenID;
|
fGenerationID = kEmptyGenID;
|
||||||
|
fSegmentMask = 0;
|
||||||
fIsOval = false;
|
fIsOval = false;
|
||||||
SkDEBUGCODE(fEditorsAttached = 0;)
|
SkDEBUGCODE(fEditorsAttached = 0;)
|
||||||
SkDEBUGCODE(this->validate();)
|
SkDEBUGCODE(this->validate();)
|
||||||
|
@ -311,6 +315,7 @@ private:
|
||||||
fBoundsIsDirty = true; // this also invalidates fIsFinite
|
fBoundsIsDirty = true; // this also invalidates fIsFinite
|
||||||
fGenerationID = 0;
|
fGenerationID = 0;
|
||||||
|
|
||||||
|
fSegmentMask = 0;
|
||||||
fIsOval = false;
|
fIsOval = false;
|
||||||
|
|
||||||
size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount;
|
size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount;
|
||||||
|
@ -340,26 +345,19 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the verb count by newVerbs and the point count be newPoints. New verbs and points
|
* Increases the verb count by numVbs and point count by the required amount.
|
||||||
* are uninitialized.
|
* The new points are uninitialized. All the new verbs are set to the specified
|
||||||
|
* verb. If 'verb' is kConic_Verb, 'weights' will return a pointer to the
|
||||||
|
* uninitialized conic weights.
|
||||||
*/
|
*/
|
||||||
void grow(int newVerbs, int newPoints) {
|
SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, int numVbs, SkScalar** weights);
|
||||||
SkDEBUGCODE(this->validate();)
|
|
||||||
size_t space = newVerbs * sizeof(uint8_t) + newPoints * sizeof (SkPoint);
|
|
||||||
this->makeSpace(space);
|
|
||||||
fVerbCnt += newVerbs;
|
|
||||||
fPointCnt += newPoints;
|
|
||||||
fFreeSpace -= space;
|
|
||||||
fBoundsIsDirty = true; // this also invalidates fIsFinite
|
|
||||||
SkDEBUGCODE(this->validate();)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the verb count 1, records the new verb, and creates room for the requisite number
|
* Increases the verb count 1, records the new verb, and creates room for the requisite number
|
||||||
* of additional points. A pointer to the first point is returned. Any new points are
|
* of additional points. A pointer to the first point is returned. Any new points are
|
||||||
* uninitialized.
|
* uninitialized.
|
||||||
*/
|
*/
|
||||||
SkPoint* growForVerb(int /*SkPath::Verb*/ verb);
|
SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that the free space available in the path ref is >= size. The verb and point counts
|
* Ensures that the free space available in the path ref is >= size. The verb and point counts
|
||||||
|
@ -425,6 +423,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable SkRect fBounds;
|
mutable SkRect fBounds;
|
||||||
|
uint8_t fSegmentMask;
|
||||||
mutable uint8_t fBoundsIsDirty;
|
mutable uint8_t fBoundsIsDirty;
|
||||||
mutable SkBool8 fIsFinite; // only meaningful if bounds are valid
|
mutable SkBool8 fIsFinite; // only meaningful if bounds are valid
|
||||||
mutable SkBool8 fIsOval;
|
mutable SkBool8 fIsOval;
|
||||||
|
|
|
@ -15,11 +15,6 @@
|
||||||
#include "SkRRect.h"
|
#include "SkRRect.h"
|
||||||
#include "SkThread.h"
|
#include "SkThread.h"
|
||||||
|
|
||||||
// This value is just made-up for now. When count is 4, calling memset was much
|
|
||||||
// slower than just writing the loop. This seems odd, and hopefully in the
|
|
||||||
// future this we appear to have been a fluke...
|
|
||||||
#define MIN_COUNT_FOR_MEMSET_TO_BE_FAST 16
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,7 +138,6 @@ void SkPath::resetFields() {
|
||||||
//fPathRef is assumed to have been emptied by the caller.
|
//fPathRef is assumed to have been emptied by the caller.
|
||||||
fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
|
fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
|
||||||
fFillType = kWinding_FillType;
|
fFillType = kWinding_FillType;
|
||||||
fSegmentMask = 0;
|
|
||||||
fConvexity = kUnknown_Convexity;
|
fConvexity = kUnknown_Convexity;
|
||||||
fDirection = kUnknown_Direction;
|
fDirection = kUnknown_Direction;
|
||||||
|
|
||||||
|
@ -182,7 +176,6 @@ void SkPath::copyFields(const SkPath& that) {
|
||||||
//fPathRef is assumed to have been set by the caller.
|
//fPathRef is assumed to have been set by the caller.
|
||||||
fLastMoveToIndex = that.fLastMoveToIndex;
|
fLastMoveToIndex = that.fLastMoveToIndex;
|
||||||
fFillType = that.fFillType;
|
fFillType = that.fFillType;
|
||||||
fSegmentMask = that.fSegmentMask;
|
|
||||||
fConvexity = that.fConvexity;
|
fConvexity = that.fConvexity;
|
||||||
fDirection = that.fDirection;
|
fDirection = that.fDirection;
|
||||||
}
|
}
|
||||||
|
@ -190,14 +183,8 @@ void SkPath::copyFields(const SkPath& that) {
|
||||||
bool operator==(const SkPath& a, const SkPath& b) {
|
bool operator==(const SkPath& a, const SkPath& b) {
|
||||||
// note: don't need to look at isConvex or bounds, since just comparing the
|
// note: don't need to look at isConvex or bounds, since just comparing the
|
||||||
// raw data is sufficient.
|
// raw data is sufficient.
|
||||||
|
|
||||||
// We explicitly check fSegmentMask as a quick-reject. We could skip it,
|
|
||||||
// since it is only a cache of info in the fVerbs, but its a fast way to
|
|
||||||
// notice a difference
|
|
||||||
|
|
||||||
return &a == &b ||
|
return &a == &b ||
|
||||||
(a.fFillType == b.fFillType && a.fSegmentMask == b.fSegmentMask &&
|
(a.fFillType == b.fFillType && *a.fPathRef.get() == *b.fPathRef.get());
|
||||||
*a.fPathRef.get() == *b.fPathRef.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPath::swap(SkPath& that) {
|
void SkPath::swap(SkPath& that) {
|
||||||
|
@ -207,7 +194,6 @@ void SkPath::swap(SkPath& that) {
|
||||||
fPathRef.swap(&that.fPathRef);
|
fPathRef.swap(&that.fPathRef);
|
||||||
SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex);
|
SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex);
|
||||||
SkTSwap<uint8_t>(fFillType, that.fFillType);
|
SkTSwap<uint8_t>(fFillType, that.fFillType);
|
||||||
SkTSwap<uint8_t>(fSegmentMask, that.fSegmentMask);
|
|
||||||
SkTSwap<uint8_t>(fConvexity, that.fConvexity);
|
SkTSwap<uint8_t>(fConvexity, that.fConvexity);
|
||||||
SkTSwap<uint8_t>(fDirection, that.fDirection);
|
SkTSwap<uint8_t>(fDirection, that.fDirection);
|
||||||
#ifdef SK_BUILD_FOR_ANDROID
|
#ifdef SK_BUILD_FOR_ANDROID
|
||||||
|
@ -674,7 +660,6 @@ void SkPath::lineTo(SkScalar x, SkScalar y) {
|
||||||
|
|
||||||
SkPathRef::Editor ed(&fPathRef);
|
SkPathRef::Editor ed(&fPathRef);
|
||||||
ed.growForVerb(kLine_Verb)->set(x, y);
|
ed.growForVerb(kLine_Verb)->set(x, y);
|
||||||
fSegmentMask |= kLine_SegmentMask;
|
|
||||||
|
|
||||||
DIRTY_AFTER_EDIT;
|
DIRTY_AFTER_EDIT;
|
||||||
}
|
}
|
||||||
|
@ -695,7 +680,6 @@ void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
|
||||||
SkPoint* pts = ed.growForVerb(kQuad_Verb);
|
SkPoint* pts = ed.growForVerb(kQuad_Verb);
|
||||||
pts[0].set(x1, y1);
|
pts[0].set(x1, y1);
|
||||||
pts[1].set(x2, y2);
|
pts[1].set(x2, y2);
|
||||||
fSegmentMask |= kQuad_SegmentMask;
|
|
||||||
|
|
||||||
DIRTY_AFTER_EDIT;
|
DIRTY_AFTER_EDIT;
|
||||||
}
|
}
|
||||||
|
@ -723,10 +707,9 @@ void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
|
||||||
this->injectMoveToIfNeeded();
|
this->injectMoveToIfNeeded();
|
||||||
|
|
||||||
SkPathRef::Editor ed(&fPathRef);
|
SkPathRef::Editor ed(&fPathRef);
|
||||||
SkPoint* pts = ed.growForConic(w);
|
SkPoint* pts = ed.growForVerb(kConic_Verb, w);
|
||||||
pts[0].set(x1, y1);
|
pts[0].set(x1, y1);
|
||||||
pts[1].set(x2, y2);
|
pts[1].set(x2, y2);
|
||||||
fSegmentMask |= kConic_SegmentMask;
|
|
||||||
|
|
||||||
DIRTY_AFTER_EDIT;
|
DIRTY_AFTER_EDIT;
|
||||||
}
|
}
|
||||||
|
@ -751,7 +734,6 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
|
||||||
pts[0].set(x1, y1);
|
pts[0].set(x1, y1);
|
||||||
pts[1].set(x2, y2);
|
pts[1].set(x2, y2);
|
||||||
pts[2].set(x3, y3);
|
pts[2].set(x3, y3);
|
||||||
fSegmentMask |= kCubic_SegmentMask;
|
|
||||||
|
|
||||||
DIRTY_AFTER_EDIT;
|
DIRTY_AFTER_EDIT;
|
||||||
}
|
}
|
||||||
|
@ -838,29 +820,19 @@ void SkPath::addPoly(const SkPoint pts[], int count, bool close) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkPathRef::Editor ed(&fPathRef);
|
fLastMoveToIndex = fPathRef->countPoints();
|
||||||
fLastMoveToIndex = ed.pathRef()->countPoints();
|
|
||||||
uint8_t* vb;
|
|
||||||
SkPoint* p;
|
|
||||||
// +close makes room for the extra kClose_Verb
|
|
||||||
ed.grow(count + close, count, &vb, &p);
|
|
||||||
|
|
||||||
memcpy(p, pts, count * sizeof(SkPoint));
|
// +close makes room for the extra kClose_Verb
|
||||||
vb[~0] = kMove_Verb;
|
SkPathRef::Editor ed(&fPathRef, count+close, count);
|
||||||
|
|
||||||
|
ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY);
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
// cast to unsigned, so if MIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to
|
SkPoint* p = ed.growForRepeatedVerb(kLine_Verb, count - 1);
|
||||||
// be 0, the compiler will remove the test/branch entirely.
|
memcpy(p, &pts[1], (count-1) * sizeof(SkPoint));
|
||||||
if ((unsigned)count >= MIN_COUNT_FOR_MEMSET_TO_BE_FAST) {
|
|
||||||
memset(vb - count, kLine_Verb, count - 1);
|
|
||||||
} else {
|
|
||||||
for (int i = 1; i < count; ++i) {
|
|
||||||
vb[~i] = kLine_Verb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fSegmentMask |= kLine_SegmentMask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close) {
|
if (close) {
|
||||||
vb[~count] = kClose_Verb;
|
ed.growForVerb(kClose_Verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
DIRTY_AFTER_EDIT;
|
DIRTY_AFTER_EDIT;
|
||||||
|
@ -1343,11 +1315,21 @@ void SkPath::addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle
|
||||||
SkPoint pts[kSkBuildQuadArcStorage];
|
SkPoint pts[kSkBuildQuadArcStorage];
|
||||||
int count = build_arc_points(oval, startAngle, sweepAngle, pts);
|
int count = build_arc_points(oval, startAngle, sweepAngle, pts);
|
||||||
|
|
||||||
this->incReserve(count);
|
SkDEBUGCODE(this->validate();)
|
||||||
this->moveTo(pts[0]);
|
SkASSERT(count & 1);
|
||||||
for (int i = 1; i < count; i += 2) {
|
|
||||||
this->quadTo(pts[i], pts[i+1]);
|
fLastMoveToIndex = fPathRef->countPoints();
|
||||||
|
|
||||||
|
SkPathRef::Editor ed(&fPathRef, 1+(count-1)/2, count);
|
||||||
|
|
||||||
|
ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY);
|
||||||
|
if (count > 1) {
|
||||||
|
SkPoint* p = ed.growForRepeatedVerb(kQuad_Verb, (count-1)/2);
|
||||||
|
memcpy(p, &pts[1], (count-1) * sizeof(SkPoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DIRTY_AFTER_EDIT;
|
||||||
|
SkDEBUGCODE(this->validate();)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1671,7 +1653,6 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const {
|
||||||
|
|
||||||
if (this != dst) {
|
if (this != dst) {
|
||||||
dst->fFillType = fFillType;
|
dst->fFillType = fFillType;
|
||||||
dst->fSegmentMask = fSegmentMask;
|
|
||||||
dst->fConvexity = fConvexity;
|
dst->fConvexity = fConvexity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2045,7 +2026,6 @@ size_t SkPath::writeToMemory(void* storage) const {
|
||||||
|
|
||||||
int32_t packed = (fConvexity << kConvexity_SerializationShift) |
|
int32_t packed = (fConvexity << kConvexity_SerializationShift) |
|
||||||
(fFillType << kFillType_SerializationShift) |
|
(fFillType << kFillType_SerializationShift) |
|
||||||
(fSegmentMask << kSegmentMask_SerializationShift) |
|
|
||||||
(fDirection << kDirection_SerializationShift)
|
(fDirection << kDirection_SerializationShift)
|
||||||
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
||||||
| (0x1 << kNewFormat_SerializationShift)
|
| (0x1 << kNewFormat_SerializationShift)
|
||||||
|
@ -2070,7 +2050,6 @@ size_t SkPath::readFromMemory(const void* storage, size_t length) {
|
||||||
|
|
||||||
fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
|
fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
|
||||||
fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
|
fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
|
||||||
fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
|
|
||||||
fDirection = (packed >> kDirection_SerializationShift) & 0x3;
|
fDirection = (packed >> kDirection_SerializationShift) & 0x3;
|
||||||
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
||||||
bool newFormat = (packed >> kNewFormat_SerializationShift) & 1;
|
bool newFormat = (packed >> kNewFormat_SerializationShift) & 1;
|
||||||
|
@ -2201,34 +2180,6 @@ void SkPath::validate() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t mask = 0;
|
|
||||||
const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbs();
|
|
||||||
for (int i = 0; i < fPathRef->countVerbs(); i++) {
|
|
||||||
switch (verbs[~i]) {
|
|
||||||
case kLine_Verb:
|
|
||||||
mask |= kLine_SegmentMask;
|
|
||||||
break;
|
|
||||||
case kQuad_Verb:
|
|
||||||
mask |= kQuad_SegmentMask;
|
|
||||||
break;
|
|
||||||
case kConic_Verb:
|
|
||||||
mask |= kConic_SegmentMask;
|
|
||||||
break;
|
|
||||||
case kCubic_Verb:
|
|
||||||
mask |= kCubic_SegmentMask;
|
|
||||||
case kMove_Verb: // these verbs aren't included in the segment mask.
|
|
||||||
case kClose_Verb:
|
|
||||||
break;
|
|
||||||
case kDone_Verb:
|
|
||||||
SkDEBUGFAIL("Done verb shouldn't be recorded.");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SkDEBUGFAIL("Unknown Verb");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SkASSERT(mask == fSegmentMask);
|
|
||||||
#endif // SK_DEBUG_PATH
|
#endif // SK_DEBUG_PATH
|
||||||
}
|
}
|
||||||
#endif // SK_DEBUG
|
#endif // SK_DEBUG
|
||||||
|
|
|
@ -28,13 +28,6 @@ SkPathRef::Editor::Editor(SkAutoTUnref<SkPathRef>* pathRef,
|
||||||
SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);)
|
SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);)
|
||||||
}
|
}
|
||||||
|
|
||||||
SkPoint* SkPathRef::Editor::growForConic(SkScalar w) {
|
|
||||||
SkDEBUGCODE(fPathRef->validate();)
|
|
||||||
SkPoint* pts = fPathRef->growForVerb(SkPath::kConic_Verb);
|
|
||||||
*fPathRef->fConicWeights.append() = w;
|
|
||||||
return pts;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
void SkPathRef::CreateEmptyImpl(SkPathRef** empty) {
|
void SkPathRef::CreateEmptyImpl(SkPathRef** empty) {
|
||||||
*empty = SkNEW(SkPathRef);
|
*empty = SkNEW(SkPathRef);
|
||||||
|
@ -105,6 +98,8 @@ void SkPathRef::CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst,
|
||||||
(*dst)->fBoundsIsDirty = true;
|
(*dst)->fBoundsIsDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(*dst)->fSegmentMask = src.fSegmentMask;
|
||||||
|
|
||||||
// It's an oval only if it stays a rect.
|
// It's an oval only if it stays a rect.
|
||||||
(*dst)->fIsOval = src.fIsOval && matrix.rectStaysRect();
|
(*dst)->fIsOval = src.fIsOval && matrix.rectStaysRect();
|
||||||
|
|
||||||
|
@ -118,6 +113,7 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
|
||||||
) {
|
) {
|
||||||
SkPathRef* ref = SkNEW(SkPathRef);
|
SkPathRef* ref = SkNEW(SkPathRef);
|
||||||
bool isOval;
|
bool isOval;
|
||||||
|
uint8_t segmentMask;
|
||||||
|
|
||||||
int32_t packed;
|
int32_t packed;
|
||||||
if (!buffer->readS32(&packed)) {
|
if (!buffer->readS32(&packed)) {
|
||||||
|
@ -130,9 +126,11 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
|
||||||
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
||||||
if (newFormat) {
|
if (newFormat) {
|
||||||
#endif
|
#endif
|
||||||
|
segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
|
||||||
isOval = (packed >> kIsOval_SerializationShift) & 1;
|
isOval = (packed >> kIsOval_SerializationShift) & 1;
|
||||||
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
|
||||||
} else {
|
} else {
|
||||||
|
segmentMask = (oldPacked >> SkPath::kOldSegmentMask_SerializationShift) & 0xF;
|
||||||
isOval = (oldPacked >> SkPath::kOldIsOval_SerializationShift) & 1;
|
isOval = (oldPacked >> SkPath::kOldIsOval_SerializationShift) & 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -159,6 +157,9 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ref->fBoundsIsDirty = false;
|
ref->fBoundsIsDirty = false;
|
||||||
|
|
||||||
|
// resetToSize clears fSegmentMask and fIsOval
|
||||||
|
ref->fSegmentMask = segmentMask;
|
||||||
ref->fIsOval = isOval;
|
ref->fIsOval = isOval;
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +173,7 @@ void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
|
||||||
(*pathRef)->fFreeSpace = (*pathRef)->currSize();
|
(*pathRef)->fFreeSpace = (*pathRef)->currSize();
|
||||||
(*pathRef)->fGenerationID = 0;
|
(*pathRef)->fGenerationID = 0;
|
||||||
(*pathRef)->fConicWeights.rewind();
|
(*pathRef)->fConicWeights.rewind();
|
||||||
|
(*pathRef)->fSegmentMask = 0;
|
||||||
(*pathRef)->fIsOval = false;
|
(*pathRef)->fIsOval = false;
|
||||||
SkDEBUGCODE((*pathRef)->validate();)
|
SkDEBUGCODE((*pathRef)->validate();)
|
||||||
} else {
|
} else {
|
||||||
|
@ -185,6 +187,14 @@ void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
|
||||||
bool SkPathRef::operator== (const SkPathRef& ref) const {
|
bool SkPathRef::operator== (const SkPathRef& ref) const {
|
||||||
SkDEBUGCODE(this->validate();)
|
SkDEBUGCODE(this->validate();)
|
||||||
SkDEBUGCODE(ref.validate();)
|
SkDEBUGCODE(ref.validate();)
|
||||||
|
|
||||||
|
// We explicitly check fSegmentMask as a quick-reject. We could skip it,
|
||||||
|
// since it is only a cache of info in the fVerbs, but its a fast way to
|
||||||
|
// notice a difference
|
||||||
|
if (fSegmentMask != ref.fSegmentMask) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID;
|
bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID;
|
||||||
#ifdef SK_RELEASE
|
#ifdef SK_RELEASE
|
||||||
if (genIDMatch) {
|
if (genIDMatch) {
|
||||||
|
@ -222,7 +232,7 @@ bool SkPathRef::operator== (const SkPathRef& ref) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPathRef::writeToBuffer(SkWBuffer* buffer) {
|
void SkPathRef::writeToBuffer(SkWBuffer* buffer) const {
|
||||||
SkDEBUGCODE(this->validate();)
|
SkDEBUGCODE(this->validate();)
|
||||||
SkDEBUGCODE(size_t beforePos = buffer->pos();)
|
SkDEBUGCODE(size_t beforePos = buffer->pos();)
|
||||||
|
|
||||||
|
@ -231,7 +241,8 @@ void SkPathRef::writeToBuffer(SkWBuffer* buffer) {
|
||||||
const SkRect& bounds = this->getBounds();
|
const SkRect& bounds = this->getBounds();
|
||||||
|
|
||||||
int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
|
int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
|
||||||
((fIsOval & 1) << kIsOval_SerializationShift);
|
((fIsOval & 1) << kIsOval_SerializationShift) |
|
||||||
|
(fSegmentMask << kSegmentMask_SerializationShift);
|
||||||
buffer->write32(packed);
|
buffer->write32(packed);
|
||||||
|
|
||||||
// TODO: write gen ID here. Problem: We don't know if we're cross process or not from
|
// TODO: write gen ID here. Problem: We don't know if we're cross process or not from
|
||||||
|
@ -248,7 +259,7 @@ void SkPathRef::writeToBuffer(SkWBuffer* buffer) {
|
||||||
SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize());
|
SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SkPathRef::writeSize() {
|
uint32_t SkPathRef::writeSize() const {
|
||||||
return uint32_t(5 * sizeof(uint32_t) +
|
return uint32_t(5 * sizeof(uint32_t) +
|
||||||
fVerbCnt * sizeof(uint8_t) +
|
fVerbCnt * sizeof(uint8_t) +
|
||||||
fPointCnt * sizeof(SkPoint) +
|
fPointCnt * sizeof(SkPoint) +
|
||||||
|
@ -273,11 +284,91 @@ void SkPathRef::copy(const SkPathRef& ref,
|
||||||
fBounds = ref.fBounds;
|
fBounds = ref.fBounds;
|
||||||
fIsFinite = ref.fIsFinite;
|
fIsFinite = ref.fIsFinite;
|
||||||
}
|
}
|
||||||
|
fSegmentMask = ref.fSegmentMask;
|
||||||
fIsOval = ref.fIsOval;
|
fIsOval = ref.fIsOval;
|
||||||
SkDEBUGCODE(this->validate();)
|
SkDEBUGCODE(this->validate();)
|
||||||
}
|
}
|
||||||
|
|
||||||
SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb) {
|
SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
|
||||||
|
int numVbs,
|
||||||
|
SkScalar** weights) {
|
||||||
|
// This value is just made-up for now. When count is 4, calling memset was much
|
||||||
|
// slower than just writing the loop. This seems odd, and hopefully in the
|
||||||
|
// future this will appear to have been a fluke...
|
||||||
|
static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16;
|
||||||
|
|
||||||
|
SkDEBUGCODE(this->validate();)
|
||||||
|
int pCnt;
|
||||||
|
bool dirtyAfterEdit = true;
|
||||||
|
switch (verb) {
|
||||||
|
case SkPath::kMove_Verb:
|
||||||
|
pCnt = numVbs;
|
||||||
|
dirtyAfterEdit = false;
|
||||||
|
break;
|
||||||
|
case SkPath::kLine_Verb:
|
||||||
|
fSegmentMask |= SkPath::kLine_SegmentMask;
|
||||||
|
pCnt = numVbs;
|
||||||
|
break;
|
||||||
|
case SkPath::kQuad_Verb:
|
||||||
|
fSegmentMask |= SkPath::kQuad_SegmentMask;
|
||||||
|
pCnt = 2 * numVbs;
|
||||||
|
break;
|
||||||
|
case SkPath::kConic_Verb:
|
||||||
|
fSegmentMask |= SkPath::kConic_SegmentMask;
|
||||||
|
pCnt = 2 * numVbs;
|
||||||
|
break;
|
||||||
|
case SkPath::kCubic_Verb:
|
||||||
|
fSegmentMask |= SkPath::kCubic_SegmentMask;
|
||||||
|
pCnt = 3 * numVbs;
|
||||||
|
break;
|
||||||
|
case SkPath::kClose_Verb:
|
||||||
|
SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb");
|
||||||
|
pCnt = 0;
|
||||||
|
dirtyAfterEdit = false;
|
||||||
|
break;
|
||||||
|
case SkPath::kDone_Verb:
|
||||||
|
SkDEBUGFAIL("growForRepeatedVerb called for kDone");
|
||||||
|
// fall through
|
||||||
|
default:
|
||||||
|
SkDEBUGFAIL("default should not be reached");
|
||||||
|
pCnt = 0;
|
||||||
|
dirtyAfterEdit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t space = numVbs * sizeof(uint8_t) + pCnt * sizeof (SkPoint);
|
||||||
|
this->makeSpace(space);
|
||||||
|
|
||||||
|
SkPoint* ret = fPoints + fPointCnt;
|
||||||
|
uint8_t* vb = fVerbs - fVerbCnt;
|
||||||
|
|
||||||
|
// cast to unsigned, so if kMIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to
|
||||||
|
// be 0, the compiler will remove the test/branch entirely.
|
||||||
|
if ((unsigned)numVbs >= kMIN_COUNT_FOR_MEMSET_TO_BE_FAST) {
|
||||||
|
memset(vb - numVbs, verb, numVbs);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < numVbs; ++i) {
|
||||||
|
vb[~i] = verb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fVerbCnt += numVbs;
|
||||||
|
fPointCnt += pCnt;
|
||||||
|
fFreeSpace -= space;
|
||||||
|
fBoundsIsDirty = true; // this also invalidates fIsFinite
|
||||||
|
if (dirtyAfterEdit) {
|
||||||
|
fIsOval = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SkPath::kConic_Verb == verb) {
|
||||||
|
SkASSERT(NULL != weights);
|
||||||
|
*weights = fConicWeights.append(numVbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkDEBUGCODE(this->validate();)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) {
|
||||||
SkDEBUGCODE(this->validate();)
|
SkDEBUGCODE(this->validate();)
|
||||||
int pCnt;
|
int pCnt;
|
||||||
bool dirtyAfterEdit = true;
|
bool dirtyAfterEdit = true;
|
||||||
|
@ -287,14 +378,19 @@ SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb) {
|
||||||
dirtyAfterEdit = false;
|
dirtyAfterEdit = false;
|
||||||
break;
|
break;
|
||||||
case SkPath::kLine_Verb:
|
case SkPath::kLine_Verb:
|
||||||
|
fSegmentMask |= SkPath::kLine_SegmentMask;
|
||||||
pCnt = 1;
|
pCnt = 1;
|
||||||
break;
|
break;
|
||||||
case SkPath::kQuad_Verb:
|
case SkPath::kQuad_Verb:
|
||||||
// fall through
|
fSegmentMask |= SkPath::kQuad_SegmentMask;
|
||||||
|
pCnt = 2;
|
||||||
|
break;
|
||||||
case SkPath::kConic_Verb:
|
case SkPath::kConic_Verb:
|
||||||
|
fSegmentMask |= SkPath::kConic_SegmentMask;
|
||||||
pCnt = 2;
|
pCnt = 2;
|
||||||
break;
|
break;
|
||||||
case SkPath::kCubic_Verb:
|
case SkPath::kCubic_Verb:
|
||||||
|
fSegmentMask |= SkPath::kCubic_SegmentMask;
|
||||||
pCnt = 3;
|
pCnt = 3;
|
||||||
break;
|
break;
|
||||||
case SkPath::kClose_Verb:
|
case SkPath::kClose_Verb:
|
||||||
|
@ -320,6 +416,11 @@ SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb) {
|
||||||
if (dirtyAfterEdit) {
|
if (dirtyAfterEdit) {
|
||||||
fIsOval = false;
|
fIsOval = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SkPath::kConic_Verb == verb) {
|
||||||
|
*fConicWeights.append() = weight;
|
||||||
|
}
|
||||||
|
|
||||||
SkDEBUGCODE(this->validate();)
|
SkDEBUGCODE(this->validate();)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -369,5 +470,36 @@ void SkPathRef::validate() const {
|
||||||
}
|
}
|
||||||
SkASSERT(SkToBool(fIsFinite) == isFinite);
|
SkASSERT(SkToBool(fIsFinite) == isFinite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SK_DEBUG_PATH
|
||||||
|
uint32_t mask = 0;
|
||||||
|
for (int i = 0; i < fVerbCnt; ++i) {
|
||||||
|
switch (fVerbs[~i]) {
|
||||||
|
case SkPath::kMove_Verb:
|
||||||
|
break;
|
||||||
|
case SkPath::kLine_Verb:
|
||||||
|
mask |= SkPath::kLine_SegmentMask;
|
||||||
|
break;
|
||||||
|
case SkPath::kQuad_Verb:
|
||||||
|
mask |= SkPath::kQuad_SegmentMask;
|
||||||
|
break;
|
||||||
|
case SkPath::kConic_Verb:
|
||||||
|
mask |= SkPath::kConic_SegmentMask;
|
||||||
|
break;
|
||||||
|
case SkPath::kCubic_Verb:
|
||||||
|
mask |= SkPath::kCubic_SegmentMask;
|
||||||
|
break;
|
||||||
|
case SkPath::kClose_Verb:
|
||||||
|
break;
|
||||||
|
case SkPath::kDone_Verb:
|
||||||
|
SkDEBUGFAIL("Done verb shouldn't be recorded.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SkDEBUGFAIL("Unknown Verb");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SkASSERT(mask == fSegmentMask);
|
||||||
|
#endif // SK_DEBUG_PATH
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3138,6 +3138,78 @@ static void test_contains(skiatest::Reporter* reporter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_pathref(skiatest::Reporter* reporter) {
|
||||||
|
static const int kRepeatCnt = 10;
|
||||||
|
|
||||||
|
SkPathRef* pathRef = SkPathRef::CreateEmpty();
|
||||||
|
SkAutoTUnref<SkPathRef> pathRef2(SkPathRef::CreateEmpty());
|
||||||
|
SkMatrix mat;
|
||||||
|
|
||||||
|
mat.setTranslate(10, 10);
|
||||||
|
|
||||||
|
SkPathRef::CreateTransformedCopy(&pathRef2, *pathRef, mat);
|
||||||
|
|
||||||
|
SkPathRef::Editor ed(&pathRef2);
|
||||||
|
|
||||||
|
{
|
||||||
|
ed.growForRepeatedVerb(SkPath::kMove_Verb, kRepeatCnt);
|
||||||
|
REPORTER_ASSERT(reporter, kRepeatCnt == pathRef2->countVerbs());
|
||||||
|
REPORTER_ASSERT(reporter, kRepeatCnt == pathRef2->countPoints());
|
||||||
|
REPORTER_ASSERT(reporter, 0 == pathRef2->getSegmentMasks());
|
||||||
|
for (int i = 0; i < kRepeatCnt; ++i) {
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kMove_Verb == pathRef2->atVerb(i));
|
||||||
|
}
|
||||||
|
ed.resetToSize(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ed.growForRepeatedVerb(SkPath::kLine_Verb, kRepeatCnt);
|
||||||
|
REPORTER_ASSERT(reporter, kRepeatCnt == pathRef2->countVerbs());
|
||||||
|
REPORTER_ASSERT(reporter, kRepeatCnt == pathRef2->countPoints());
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kLine_SegmentMask == pathRef2->getSegmentMasks());
|
||||||
|
for (int i = 0; i < kRepeatCnt; ++i) {
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kLine_Verb == pathRef2->atVerb(i));
|
||||||
|
}
|
||||||
|
ed.resetToSize(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ed.growForRepeatedVerb(SkPath::kQuad_Verb, kRepeatCnt);
|
||||||
|
REPORTER_ASSERT(reporter, kRepeatCnt == pathRef2->countVerbs());
|
||||||
|
REPORTER_ASSERT(reporter, 2*kRepeatCnt == pathRef2->countPoints());
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kQuad_SegmentMask == pathRef2->getSegmentMasks());
|
||||||
|
for (int i = 0; i < kRepeatCnt; ++i) {
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == pathRef2->atVerb(i));
|
||||||
|
}
|
||||||
|
ed.resetToSize(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SkScalar* weights = NULL;
|
||||||
|
ed.growForRepeatedVerb(SkPath::kConic_Verb, kRepeatCnt, &weights);
|
||||||
|
REPORTER_ASSERT(reporter, kRepeatCnt == pathRef2->countVerbs());
|
||||||
|
REPORTER_ASSERT(reporter, 2*kRepeatCnt == pathRef2->countPoints());
|
||||||
|
REPORTER_ASSERT(reporter, kRepeatCnt == pathRef2->countWeights());
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kConic_SegmentMask == pathRef2->getSegmentMasks());
|
||||||
|
REPORTER_ASSERT(reporter, NULL != weights);
|
||||||
|
for (int i = 0; i < kRepeatCnt; ++i) {
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kConic_Verb == pathRef2->atVerb(i));
|
||||||
|
}
|
||||||
|
ed.resetToSize(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ed.growForRepeatedVerb(SkPath::kCubic_Verb, kRepeatCnt);
|
||||||
|
REPORTER_ASSERT(reporter, kRepeatCnt == pathRef2->countVerbs());
|
||||||
|
REPORTER_ASSERT(reporter, 3*kRepeatCnt == pathRef2->countPoints());
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kCubic_SegmentMask == pathRef2->getSegmentMasks());
|
||||||
|
for (int i = 0; i < kRepeatCnt; ++i) {
|
||||||
|
REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == pathRef2->atVerb(i));
|
||||||
|
}
|
||||||
|
ed.resetToSize(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void test_operatorEqual(skiatest::Reporter* reporter) {
|
static void test_operatorEqual(skiatest::Reporter* reporter) {
|
||||||
SkPath a;
|
SkPath a;
|
||||||
SkPath b;
|
SkPath b;
|
||||||
|
@ -3297,5 +3369,6 @@ DEF_TEST(Path, reporter) {
|
||||||
test_conicTo_special_case(reporter);
|
test_conicTo_special_case(reporter);
|
||||||
test_get_point(reporter);
|
test_get_point(reporter);
|
||||||
test_contains(reporter);
|
test_contains(reporter);
|
||||||
|
test_pathref(reporter);
|
||||||
PathTest_Private::TestPathTo(reporter);
|
PathTest_Private::TestPathTo(reporter);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче