| Index: src/gpu/GrShape.cpp
|
| diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp
|
| index 45ddb777789214c95714a2e75cd7fc20d329b519..5ffd32d46de2f36b61f8093d614e8e408624f49d 100644
|
| --- a/src/gpu/GrShape.cpp
|
| +++ b/src/gpu/GrShape.cpp
|
| @@ -14,10 +14,10 @@ GrShape& GrShape::operator=(const GrShape& that) {
|
| case Type::kEmpty:
|
| break;
|
| case Type::kRRect:
|
| - fRRectData.fRRect = that.fRRectData.fRRect;
|
| - fRRectData.fDir = that.fRRectData.fDir;
|
| - fRRectData.fStart = that.fRRectData.fStart;
|
| - fRRectData.fInverted = that.fRRectData.fInverted;
|
| + fRRectData = that.fRRectData;
|
| + break;
|
| + case Type::kLine:
|
| + fLineData = that.fLineData;
|
| break;
|
| case Type::kPath:
|
| fPathData.fGenID = that.fPathData.fGenID;
|
| @@ -29,11 +29,29 @@ GrShape& GrShape::operator=(const GrShape& that) {
|
| return *this;
|
| }
|
|
|
| -const SkRect& GrShape::bounds() const {
|
| +SkRect GrShape::bounds() const {
|
| static constexpr SkRect kEmpty = SkRect::MakeEmpty();
|
| switch (fType) {
|
| case Type::kEmpty:
|
| return kEmpty;
|
| + case Type::kLine: {
|
| + SkRect bounds;
|
| + if (fLineData.fPts[0].fX < fLineData.fPts[1].fX) {
|
| + bounds.fLeft = fLineData.fPts[0].fX;
|
| + bounds.fRight = fLineData.fPts[1].fX;
|
| + } else {
|
| + bounds.fLeft = fLineData.fPts[1].fX;
|
| + bounds.fRight = fLineData.fPts[0].fX;
|
| + }
|
| + if (fLineData.fPts[0].fY < fLineData.fPts[1].fY) {
|
| + bounds.fTop = fLineData.fPts[0].fY;
|
| + bounds.fBottom = fLineData.fPts[1].fY;
|
| + } else {
|
| + bounds.fTop = fLineData.fPts[1].fY;
|
| + bounds.fBottom = fLineData.fPts[0].fY;
|
| + }
|
| + return bounds;
|
| + }
|
| case Type::kRRect:
|
| return fRRectData.fRRect.getBounds();
|
| case Type::kPath:
|
| @@ -43,12 +61,13 @@ const SkRect& GrShape::bounds() const {
|
| return kEmpty;
|
| }
|
|
|
| -void GrShape::styledBounds(SkRect* bounds) const {
|
| +SkRect GrShape::styledBounds() const {
|
| if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) {
|
| - *bounds = SkRect::MakeEmpty();
|
| - } else {
|
| - fStyle.adjustBounds(bounds, this->bounds());
|
| + return SkRect::MakeEmpty();
|
| }
|
| + SkRect bounds;
|
| + fStyle.adjustBounds(&bounds, this->bounds());
|
| + return bounds;
|
| }
|
|
|
| int GrShape::unstyledKeySize() const {
|
| @@ -63,6 +82,10 @@ int GrShape::unstyledKeySize() const {
|
| SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t));
|
| // + 1 for the direction, start index, and inverseness.
|
| return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1;
|
| + case Type::kLine:
|
| + GR_STATIC_ASSERT(2 * sizeof(uint32_t) == sizeof(SkPoint));
|
| + // 4 for the end points and 1 for the inverseness
|
| + return 5;
|
| case Type::kPath:
|
| if (0 == fPathData.fGenID) {
|
| return -1;
|
| @@ -94,6 +117,11 @@ void GrShape::writeUnstyledKey(uint32_t* key) const {
|
| *key++ |= fRRectData.fStart;
|
| SkASSERT(fRRectData.fStart < 8);
|
| break;
|
| + case Type::kLine:
|
| + memcpy(key, fLineData.fPts, 2 * sizeof(SkPoint));
|
| + key += 4;
|
| + *key++ = fLineData.fInverted ? 1 : 0;
|
| + break;
|
| case Type::kPath:
|
| SkASSERT(fPathData.fGenID);
|
| *key++ = fPathData.fGenID;
|
| @@ -159,10 +187,10 @@ GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) {
|
| case Type::kEmpty:
|
| break;
|
| case Type::kRRect:
|
| - fRRectData.fRRect = that.fRRectData.fRRect;
|
| - fRRectData.fDir = that.fRRectData.fDir;
|
| - fRRectData.fStart = that.fRRectData.fStart;
|
| - fRRectData.fInverted = that.fRRectData.fInverted;
|
| + fRRectData = that.fRRectData;
|
| + break;
|
| + case Type::kLine:
|
| + fLineData = that.fLineData;
|
| break;
|
| case Type::kPath:
|
| fPathData.fGenID = that.fPathData.fGenID;
|
| @@ -266,8 +294,14 @@ void GrShape::attemptToSimplifyPath() {
|
| SkPath::Direction rrectDir;
|
| unsigned rrectStart;
|
| bool inverted = this->path().isInverseFillType();
|
| + SkPoint pts[2];
|
| if (this->path().isEmpty()) {
|
| this->changeType(Type::kEmpty);
|
| + } else if (this->path().isLine(pts)) {
|
| + this->changeType(Type::kLine);
|
| + fLineData.fPts[0] = pts[0];
|
| + fLineData.fPts[1] = pts[1];
|
| + fLineData.fInverted = inverted;
|
| } else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) {
|
| this->changeType(Type::kRRect);
|
| fRRectData.fRRect = rrect;
|
| @@ -313,6 +347,8 @@ void GrShape::attemptToSimplifyPath() {
|
| fInheritedKey.reset(0);
|
| if (Type::kRRect == fType) {
|
| this->attemptToSimplifyRRect();
|
| + } else if (Type::kLine == fType) {
|
| + this->attemptToSimplifyLine();
|
| }
|
| } else {
|
| if (fInheritedKey.count() || this->path().isVolatile()) {
|
| @@ -321,13 +357,8 @@ void GrShape::attemptToSimplifyPath() {
|
| fPathData.fGenID = this->path().getGenerationID();
|
| }
|
| if (this->style().isSimpleFill()) {
|
| - // Filled paths are treated as though all their contours were closed.
|
| - // Since SkPath doesn't track individual contours, this will only close the last. :(
|
| - // There is no point in closing lines, though, since they loose their line-ness.
|
| - if (!this->path().isLine(nullptr)) {
|
| - this->path().close();
|
| - this->path().setIsVolatile(true);
|
| - }
|
| + this->path().close();
|
| + this->path().setIsVolatile(true);
|
| }
|
| if (!this->style().hasNonDashPathEffect()) {
|
| if (this->style().strokeRec().getStyle() == SkStrokeRec::kStroke_Style ||
|
| @@ -368,3 +399,21 @@ void GrShape::attemptToSimplifyRRect() {
|
| fRRectData.fInverted = false;
|
| }
|
| }
|
| +
|
| +void GrShape::attemptToSimplifyLine() {
|
| + if (fStyle.isSimpleFill() && !fLineData.fInverted) {
|
| + this->changeType(Type::kEmpty);
|
| + } else {
|
| + // Only path effects could care about the order of the points. Otherwise canonicalize
|
| + // the point order
|
| + if (!fStyle.hasPathEffect()) {
|
| + SkPoint* pts = fLineData.fPts;
|
| + if (pts[1].fY < pts[0].fY || (pts[1].fY == pts[0].fY && pts[1].fX < pts[0].fX)) {
|
| + SkTSwap(pts[0], pts[1]);
|
| + }
|
| + } else if (fStyle.isDashed()) {
|
| + // Dashing ignores inverseness.
|
| + fLineData.fInverted = false;
|
| + }
|
| + }
|
| +}
|
|
|