| Index: src/gpu/batches/GrAAStrokeRectBatch.cpp
|
| diff --git a/src/gpu/batches/GrAAStrokeRectBatch.cpp b/src/gpu/batches/GrAAStrokeRectBatch.cpp
|
| index 3e0893236f8314806f678dd3c0122bdf2b3e0d35..da77dca6b33fe0d6f3c989356ed267ff0f71d95e 100644
|
| --- a/src/gpu/batches/GrAAStrokeRectBatch.cpp
|
| +++ b/src/gpu/batches/GrAAStrokeRectBatch.cpp
|
| @@ -21,6 +21,79 @@ static void set_inset_fan(SkPoint* pts, size_t stride,
|
| r.fRight - dx, r.fBottom - dy, stride);
|
| }
|
|
|
| +// We support all hairlines, bevels, and miters, but not round joins. Also, check whether the miter
|
| +// limit makes a miter join effectively beveled.
|
| +inline static bool allowed_stroke(const SkStrokeRec& stroke, bool* isMiter) {
|
| + SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style ||
|
| + stroke.getStyle() == SkStrokeRec::kHairline_Style);
|
| + // For hairlines, make bevel and round joins appear the same as mitered ones.
|
| + if (!stroke.getWidth()) {
|
| + *isMiter = true;
|
| + return true;
|
| + }
|
| + if (stroke.getJoin() == SkPaint::kBevel_Join) {
|
| + *isMiter = false;
|
| + return true;
|
| + }
|
| + if (stroke.getJoin() == SkPaint::kMiter_Join) {
|
| + *isMiter = stroke.getMiter() >= SK_ScalarSqrt2;
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +static void compute_rects(SkRect* devOutside, SkRect* devOutsideAssist, SkRect* devInside,
|
| + bool* isDegenerate, const SkMatrix& viewMatrix, const SkRect& rect,
|
| + SkScalar strokeWidth, bool miterStroke) {
|
| + SkRect devRect;
|
| + viewMatrix.mapRect(&devRect, rect);
|
| +
|
| + SkVector devStrokeSize;
|
| + if (strokeWidth > 0) {
|
| + devStrokeSize.set(strokeWidth, strokeWidth);
|
| + viewMatrix.mapVectors(&devStrokeSize, 1);
|
| + devStrokeSize.setAbs(devStrokeSize);
|
| + } else {
|
| + devStrokeSize.set(SK_Scalar1, SK_Scalar1);
|
| + }
|
| +
|
| + const SkScalar dx = devStrokeSize.fX;
|
| + const SkScalar dy = devStrokeSize.fY;
|
| + const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf);
|
| + const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf);
|
| +
|
| + *devOutside = devRect;
|
| + *devOutsideAssist = devRect;
|
| + *devInside = devRect;
|
| +
|
| + devOutside->outset(rx, ry);
|
| + devInside->inset(rx, ry);
|
| +
|
| + // If we have a degenerate stroking rect(ie the stroke is larger than inner rect) then we
|
| + // make a degenerate inside rect to avoid double hitting. We will also jam all of the points
|
| + // together when we render these rects.
|
| + SkScalar spare;
|
| + {
|
| + SkScalar w = devRect.width() - dx;
|
| + SkScalar h = devRect.height() - dy;
|
| + spare = SkTMin(w, h);
|
| + }
|
| +
|
| + *isDegenerate = spare <= 0;
|
| + if (*isDegenerate) {
|
| + devInside->fLeft = devInside->fRight = devRect.centerX();
|
| + devInside->fTop = devInside->fBottom = devRect.centerY();
|
| + }
|
| +
|
| + // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist)
|
| + // to draw the outside of the octagon. Because there are 8 vertices on the outer
|
| + // edge, while vertex number of inner edge is 4, the same as miter-stroke.
|
| + if (!miterStroke) {
|
| + devOutside->inset(0, ry);
|
| + devOutsideAssist->outset(0, ry);
|
| + }
|
| +}
|
| +
|
| static sk_sp<GrGeometryProcessor> create_stroke_rect_gp(bool tweakAlphaForCoverage,
|
| const SkMatrix& viewMatrix,
|
| bool usesLocalCoords,
|
| @@ -47,17 +120,36 @@ class AAStrokeRectBatch : public GrVertexBatch {
|
| public:
|
| DEFINE_BATCH_CLASS_ID
|
|
|
| - // TODO support AA rotated stroke rects by copying around view matrices
|
| - struct Geometry {
|
| - SkRect fDevOutside;
|
| - SkRect fDevOutsideAssist;
|
| - SkRect fDevInside;
|
| - GrColor fColor;
|
| - bool fDegenerate;
|
| - };
|
| + AAStrokeRectBatch(GrColor color, const SkMatrix& viewMatrix,
|
| + const SkRect& devOutside, const SkRect& devInside)
|
| + : INHERITED(ClassID())
|
| + , fViewMatrix(viewMatrix) {
|
| + SkASSERT(!devOutside.isEmpty())
|
| + SkASSERT(!devInside.isEmpty())
|
|
|
| - static AAStrokeRectBatch* Create(const SkMatrix& viewMatrix, bool miterStroke) {
|
| - return new AAStrokeRectBatch(viewMatrix, miterStroke);
|
| + fGeoData.emplace_back(Geometry{color, devOutside, devOutside, devInside, false});
|
| + fBounds = devOutside;
|
| + fMiterStroke = true;
|
| + }
|
| +
|
| +
|
| + static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
|
| + const SkStrokeRec& stroke) {
|
| + bool isMiter;
|
| + if (!allowed_stroke(stroke, &isMiter)) {
|
| + return nullptr;
|
| + }
|
| +
|
| + AAStrokeRectBatch* batch = new AAStrokeRectBatch();
|
| + batch->fMiterStroke = isMiter;
|
| + Geometry& geo = batch->fGeoData.push_back();
|
| + compute_rects(&geo.fDevOutside, &geo.fDevOutsideAssist, &geo.fDevInside, &geo.fDegenerate,
|
| + viewMatrix, rect, stroke.getWidth(), isMiter);
|
| + geo.fColor = color;
|
| + batch->fBounds = geo.fDevOutside;
|
| + batch->fBounds.join(geo.fDevOutsideAssist);
|
| + batch->fViewMatrix = viewMatrix;
|
| + return batch;
|
| }
|
|
|
| const char* name() const override { return "AAStrokeRect"; }
|
| @@ -70,51 +162,12 @@ public:
|
| coverage->setUnknownSingleComponent();
|
| }
|
|
|
| - SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
|
| -
|
| - bool canAppend(const SkMatrix& viewMatrix, bool miterStroke) {
|
| - return fViewMatrix.cheapEqualTo(viewMatrix) && fMiterStroke == miterStroke;
|
| - }
|
| -
|
| - void append(GrColor color, const SkRect& devOutside, const SkRect& devOutsideAssist,
|
| - const SkRect& devInside, bool degenerate) {
|
| - Geometry& geometry = fGeoData.push_back();
|
| - geometry.fColor = color;
|
| - geometry.fDevOutside = devOutside;
|
| - geometry.fDevOutsideAssist = devOutsideAssist;
|
| - geometry.fDevInside = devInside;
|
| - geometry.fDegenerate = degenerate;
|
| - }
|
| -
|
| - void appendAndUpdateBounds(GrColor color, const SkRect& devOutside,
|
| - const SkRect& devOutsideAssist, const SkRect& devInside,
|
| - bool degenerate) {
|
| - this->append(color, devOutside, devOutsideAssist, devInside, degenerate);
|
| -
|
| - SkRect bounds;
|
| - this->updateBounds(&bounds, fGeoData.back());
|
| - this->joinBounds(bounds);
|
| - }
|
| -
|
| - void init() { this->updateBounds(&fBounds, fGeoData[0]); }
|
| -
|
| private:
|
| - void updateBounds(SkRect* bounds, const Geometry& geo) {
|
| - // If we have miterstroke then we inset devOutside and outset devOutsideAssist, so we need
|
| - // the join for proper bounds
|
| - *bounds = geo.fDevOutside;
|
| - bounds->join(geo.fDevOutsideAssist);
|
| - }
|
| + AAStrokeRectBatch() : INHERITED(ClassID()) {}
|
|
|
| void onPrepareDraws(Target*) const override;
|
| void initBatchTracker(const GrXPOverridesForBatch&) override;
|
|
|
| - AAStrokeRectBatch(const SkMatrix& viewMatrix,bool miterStroke)
|
| - : INHERITED(ClassID()) {
|
| - fViewMatrix = viewMatrix;
|
| - fMiterStroke = miterStroke;
|
| - }
|
| -
|
| static const int kMiterIndexCnt = 3 * 24;
|
| static const int kMiterVertexCnt = 16;
|
| static const int kNumMiterRectsInIndexBuffer = 256;
|
| @@ -130,7 +183,6 @@ private:
|
| bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
|
| bool colorIgnored() const { return fBatch.fColorIgnored; }
|
| bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
|
| - const Geometry& geometry() const { return fGeoData[0]; }
|
| const SkMatrix& viewMatrix() const { return fViewMatrix; }
|
| bool miterStroke() const { return fMiterStroke; }
|
|
|
| @@ -157,6 +209,15 @@ private:
|
| bool fCanTweakAlphaForCoverage;
|
| };
|
|
|
| + // TODO support AA rotated stroke rects by copying around view matrices
|
| + struct Geometry {
|
| + GrColor fColor;
|
| + SkRect fDevOutside;
|
| + SkRect fDevOutsideAssist;
|
| + SkRect fDevInside;
|
| + bool fDegenerate;
|
| + };
|
| +
|
| BatchTracker fBatch;
|
| SkSTArray<1, Geometry, true> fGeoData;
|
| SkMatrix fViewMatrix;
|
| @@ -352,7 +413,7 @@ bool AAStrokeRectBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) {
|
| if (this->color() != that->color()) {
|
| fBatch.fColor = GrColor_ILLEGAL;
|
| }
|
| - fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
|
| + fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
|
| this->joinBounds(that->bounds());
|
| return true;
|
| }
|
| @@ -516,114 +577,23 @@ void AAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices,
|
| }
|
| }
|
|
|
| -// We support all hairlines, bevels, and miters, but not round joins. Also, check whether the miter
|
| -// limit makes a miter join effectively beveled.
|
| -inline static bool allowed_stroke(const SkStrokeRec& stroke, bool* isMiter) {
|
| - SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style ||
|
| - stroke.getStyle() == SkStrokeRec::kHairline_Style);
|
| - // For hairlines, make bevel and round joins appear the same as mitered ones.
|
| - if (!stroke.getWidth()) {
|
| - *isMiter = true;
|
| - return true;
|
| - }
|
| - if (stroke.getJoin() == SkPaint::kBevel_Join) {
|
| - *isMiter = false;
|
| - return true;
|
| - }
|
| - if (stroke.getJoin() == SkPaint::kMiter_Join) {
|
| - *isMiter = stroke.getMiter() >= SK_ScalarSqrt2;
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -static void compute_rects(SkRect* devOutside, SkRect* devOutsideAssist, SkRect* devInside,
|
| - bool* isDegenerate, const SkMatrix& viewMatrix, const SkRect& rect,
|
| - SkScalar strokeWidth, bool miterStroke) {
|
| - SkRect devRect;
|
| - viewMatrix.mapRect(&devRect, rect);
|
| -
|
| - SkVector devStrokeSize;
|
| - if (strokeWidth > 0) {
|
| - devStrokeSize.set(strokeWidth, strokeWidth);
|
| - viewMatrix.mapVectors(&devStrokeSize, 1);
|
| - devStrokeSize.setAbs(devStrokeSize);
|
| - } else {
|
| - devStrokeSize.set(SK_Scalar1, SK_Scalar1);
|
| - }
|
| -
|
| - const SkScalar dx = devStrokeSize.fX;
|
| - const SkScalar dy = devStrokeSize.fY;
|
| - const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf);
|
| - const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf);
|
| -
|
| - *devOutside = devRect;
|
| - *devOutsideAssist = devRect;
|
| - *devInside = devRect;
|
| -
|
| - devOutside->outset(rx, ry);
|
| - devInside->inset(rx, ry);
|
| -
|
| - // If we have a degenerate stroking rect(ie the stroke is larger than inner rect) then we
|
| - // make a degenerate inside rect to avoid double hitting. We will also jam all of the points
|
| - // together when we render these rects.
|
| - SkScalar spare;
|
| - {
|
| - SkScalar w = devRect.width() - dx;
|
| - SkScalar h = devRect.height() - dy;
|
| - spare = SkTMin(w, h);
|
| - }
|
| -
|
| - *isDegenerate = spare <= 0;
|
| - if (*isDegenerate) {
|
| - devInside->fLeft = devInside->fRight = devRect.centerX();
|
| - devInside->fTop = devInside->fBottom = devRect.centerY();
|
| - }
|
| -
|
| - // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist)
|
| - // to draw the outside of the octagon. Because there are 8 vertices on the outer
|
| - // edge, while vertex number of inner edge is 4, the same as miter-stroke.
|
| - if (!miterStroke) {
|
| - devOutside->inset(0, ry);
|
| - devOutsideAssist->outset(0, ry);
|
| - }
|
| -}
|
| -
|
| namespace GrAAStrokeRectBatch {
|
|
|
| GrDrawBatch* CreateFillBetweenRects(GrColor color,
|
| const SkMatrix& viewMatrix,
|
| const SkRect& devOutside,
|
| const SkRect& devInside) {
|
| - SkASSERT(!devOutside.isEmpty())
|
| - SkASSERT(!devInside.isEmpty())
|
| - AAStrokeRectBatch* batch = AAStrokeRectBatch::Create(viewMatrix, true);
|
| - batch->append(color, devOutside, devOutside, devInside, false);
|
| - batch->init();
|
| - return batch;
|
| + return new AAStrokeRectBatch(color, viewMatrix, devOutside, devInside);
|
| }
|
|
|
| GrDrawBatch* Create(GrColor color,
|
| const SkMatrix& viewMatrix,
|
| const SkRect& rect,
|
| const SkStrokeRec& stroke) {
|
| - bool isMiterStroke;
|
| - if (!allowed_stroke(stroke, &isMiterStroke)) {
|
| - return nullptr;
|
| - }
|
| - AAStrokeRectBatch* batch = AAStrokeRectBatch::Create(viewMatrix, isMiterStroke);
|
| -
|
| - SkRect devOutside, devOutsideAssist, devInside;
|
| - bool isDegenerate;
|
| - compute_rects(&devOutside, &devOutsideAssist, &devInside, &isDegenerate, viewMatrix,
|
| - rect, stroke.getWidth(), isMiterStroke);
|
| -
|
| - batch->append(color, devOutside, devOutsideAssist, devInside, isDegenerate);
|
| - batch->init();
|
| - return batch;
|
| + return AAStrokeRectBatch::Create(color, viewMatrix, rect, stroke);
|
| }
|
|
|
| -};
|
| +}
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|