Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrAAStrokeRectBatch.h" | 8 #include "GrAAStrokeRectBatch.h" |
| 9 | 9 |
| 10 #include "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
| 11 #include "GrDefaultGeoProcFactory.h" | 11 #include "GrDefaultGeoProcFactory.h" |
| 12 #include "GrResourceKey.h" | 12 #include "GrResourceKey.h" |
| 13 #include "GrResourceProvider.h" | 13 #include "GrResourceProvider.h" |
| 14 | 14 |
| 15 GR_DECLARE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey); | 15 GR_DECLARE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey); |
| 16 GR_DECLARE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey); | 16 GR_DECLARE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey); |
| 17 | 17 |
| 18 static void set_inset_fan(SkPoint* pts, size_t stride, | 18 static void set_inset_fan(SkPoint* pts, size_t stride, |
| 19 const SkRect& r, SkScalar dx, SkScalar dy) { | 19 const SkRect& r, SkScalar dx, SkScalar dy) { |
| 20 pts->setRectFan(r.fLeft + dx, r.fTop + dy, | 20 pts->setRectFan(r.fLeft + dx, r.fTop + dy, |
| 21 r.fRight - dx, r.fBottom - dy, stride); | 21 r.fRight - dx, r.fBottom - dy, stride); |
| 22 } | 22 } |
| 23 | 23 |
| 24 inline static bool is_miter(const SkStrokeRec& stroke) { | |
|
bsalomon
2016/07/01 17:56:37
These two functions are just moved from below.
| |
| 25 // For hairlines, make bevel and round joins appear the same as mitered ones . | |
| 26 // small miter limit means right angles show bevel... | |
| 27 if ((stroke.getWidth() > 0) && (stroke.getJoin() != SkPaint::kMiter_Join || | |
| 28 stroke.getMiter() < SK_ScalarSqrt2)) { | |
| 29 return false; | |
| 30 } | |
| 31 return true; | |
| 32 } | |
| 33 | |
| 34 static void compute_rects(SkRect* devOutside, SkRect* devOutsideAssist, SkRect* devInside, | |
| 35 bool* isDegenerate, const SkMatrix& viewMatrix, const SkRect& rect, | |
| 36 SkScalar strokeWidth, bool miterStroke) { | |
| 37 SkRect devRect; | |
| 38 viewMatrix.mapRect(&devRect, rect); | |
| 39 | |
| 40 SkVector devStrokeSize; | |
| 41 if (strokeWidth > 0) { | |
| 42 devStrokeSize.set(strokeWidth, strokeWidth); | |
| 43 viewMatrix.mapVectors(&devStrokeSize, 1); | |
| 44 devStrokeSize.setAbs(devStrokeSize); | |
| 45 } else { | |
| 46 devStrokeSize.set(SK_Scalar1, SK_Scalar1); | |
| 47 } | |
| 48 | |
| 49 const SkScalar dx = devStrokeSize.fX; | |
| 50 const SkScalar dy = devStrokeSize.fY; | |
| 51 const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf); | |
| 52 const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf); | |
| 53 | |
| 54 *devOutside = devRect; | |
| 55 *devOutsideAssist = devRect; | |
| 56 *devInside = devRect; | |
| 57 | |
| 58 devOutside->outset(rx, ry); | |
| 59 devInside->inset(rx, ry); | |
| 60 | |
| 61 // If we have a degenerate stroking rect(ie the stroke is larger than inner rect) then we | |
| 62 // make a degenerate inside rect to avoid double hitting. We will also jam all of the points | |
| 63 // together when we render these rects. | |
| 64 SkScalar spare; | |
| 65 { | |
| 66 SkScalar w = devRect.width() - dx; | |
| 67 SkScalar h = devRect.height() - dy; | |
| 68 spare = SkTMin(w, h); | |
| 69 } | |
| 70 | |
| 71 *isDegenerate = spare <= 0; | |
| 72 if (*isDegenerate) { | |
| 73 devInside->fLeft = devInside->fRight = devRect.centerX(); | |
| 74 devInside->fTop = devInside->fBottom = devRect.centerY(); | |
| 75 } | |
| 76 | |
| 77 // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist) | |
| 78 // to draw the outside of the octagon. Because there are 8 vertices on the o uter | |
| 79 // edge, while vertex number of inner edge is 4, the same as miter-stroke. | |
| 80 if (!miterStroke) { | |
| 81 devOutside->inset(0, ry); | |
| 82 devOutsideAssist->outset(0, ry); | |
| 83 } | |
| 84 } | |
| 85 | |
| 24 static sk_sp<GrGeometryProcessor> create_stroke_rect_gp(bool tweakAlphaForCovera ge, | 86 static sk_sp<GrGeometryProcessor> create_stroke_rect_gp(bool tweakAlphaForCovera ge, |
| 25 const SkMatrix& viewMatr ix, | 87 const SkMatrix& viewMatr ix, |
| 26 bool usesLocalCoords, | 88 bool usesLocalCoords, |
| 27 bool coverageIgnored) { | 89 bool coverageIgnored) { |
| 28 using namespace GrDefaultGeoProcFactory; | 90 using namespace GrDefaultGeoProcFactory; |
| 29 | 91 |
| 30 Color color(Color::kAttribute_Type); | 92 Color color(Color::kAttribute_Type); |
| 31 Coverage::Type coverageType; | 93 Coverage::Type coverageType; |
| 32 // TODO remove coverage if coverage is ignored | 94 // TODO remove coverage if coverage is ignored |
| 33 /*if (coverageIgnored) { | 95 /*if (coverageIgnored) { |
| 34 coverageType = Coverage::kNone_Type; | 96 coverageType = Coverage::kNone_Type; |
| 35 } else*/ if (tweakAlphaForCoverage) { | 97 } else*/ if (tweakAlphaForCoverage) { |
| 36 coverageType = Coverage::kSolid_Type; | 98 coverageType = Coverage::kSolid_Type; |
| 37 } else { | 99 } else { |
| 38 coverageType = Coverage::kAttribute_Type; | 100 coverageType = Coverage::kAttribute_Type; |
| 39 } | 101 } |
| 40 Coverage coverage(coverageType); | 102 Coverage coverage(coverageType); |
| 41 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type : | 103 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type : |
| 42 LocalCoords::kUnused_Type); | 104 LocalCoords::kUnused_Type); |
| 43 return MakeForDeviceSpace(color, coverage, localCoords, viewMatrix); | 105 return MakeForDeviceSpace(color, coverage, localCoords, viewMatrix); |
| 44 } | 106 } |
| 45 | 107 |
| 46 class AAStrokeRectBatch : public GrVertexBatch { | 108 class AAStrokeRectBatch : public GrVertexBatch { |
| 47 public: | 109 public: |
| 48 DEFINE_BATCH_CLASS_ID | 110 DEFINE_BATCH_CLASS_ID |
| 49 | 111 |
| 50 // TODO support AA rotated stroke rects by copying around view matrices | 112 AAStrokeRectBatch(GrColor color, const SkMatrix& viewMatrix, |
| 51 struct Geometry { | 113 const SkRect& devOutside, const SkRect& devInside) : INHER ITED(ClassID()) { |
| 52 SkRect fDevOutside; | 114 SkASSERT(!devOutside.isEmpty()) |
| 53 SkRect fDevOutsideAssist; | 115 SkASSERT(!devInside.isEmpty()) |
| 54 SkRect fDevInside; | |
| 55 GrColor fColor; | |
| 56 bool fDegenerate; | |
| 57 }; | |
| 58 | 116 |
| 59 static AAStrokeRectBatch* Create(const SkMatrix& viewMatrix, bool miterStrok e) { | 117 fGeoData.emplace_back(Geometry{color, devOutside, devOutside, devInside, false}); |
| 60 return new AAStrokeRectBatch(viewMatrix, miterStroke); | 118 fBounds = devOutside; |
| 119 fMiterStroke = true; | |
| 120 } | |
| 121 | |
| 122 AAStrokeRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& r ect, | |
| 123 const SkStrokeRec& stroke) : INHERITED(ClassID()) { | |
| 124 fMiterStroke = is_miter(stroke); | |
| 125 | |
| 126 SkRect devOutside, devOutsideAssist, devInside; | |
| 127 bool isDegenerate; | |
| 128 compute_rects(&devOutside, &devOutsideAssist, &devInside, &isDegenerate, viewMatrix, | |
| 129 rect, stroke.getWidth(), fMiterStroke); | |
| 130 | |
| 131 fGeoData.emplace_back(Geometry{color, devOutside, devOutsideAssist, devI nside, | |
| 132 isDegenerate}); | |
| 133 fBounds = devOutside; | |
| 134 fBounds.join(devOutsideAssist); | |
| 61 } | 135 } |
| 62 | 136 |
| 63 const char* name() const override { return "AAStrokeRect"; } | 137 const char* name() const override { return "AAStrokeRect"; } |
| 64 | 138 |
| 65 void computePipelineOptimizations(GrInitInvariantOutput* color, | 139 void computePipelineOptimizations(GrInitInvariantOutput* color, |
| 66 GrInitInvariantOutput* coverage, | 140 GrInitInvariantOutput* coverage, |
| 67 GrBatchToXPOverrides* overrides) const ove rride { | 141 GrBatchToXPOverrides* overrides) const ove rride { |
| 68 // When this is called on a batch, there is only one geometry bundle | 142 // When this is called on a batch, there is only one geometry bundle |
| 69 color->setKnownFourComponents(fGeoData[0].fColor); | 143 color->setKnownFourComponents(fGeoData[0].fColor); |
| 70 coverage->setUnknownSingleComponent(); | 144 coverage->setUnknownSingleComponent(); |
| 71 } | 145 } |
| 72 | 146 |
| 73 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 74 | |
| 75 bool canAppend(const SkMatrix& viewMatrix, bool miterStroke) { | |
| 76 return fViewMatrix.cheapEqualTo(viewMatrix) && fMiterStroke == miterStro ke; | |
| 77 } | |
| 78 | |
| 79 void append(GrColor color, const SkRect& devOutside, const SkRect& devOutsid eAssist, | |
| 80 const SkRect& devInside, bool degenerate) { | |
| 81 Geometry& geometry = fGeoData.push_back(); | |
| 82 geometry.fColor = color; | |
| 83 geometry.fDevOutside = devOutside; | |
| 84 geometry.fDevOutsideAssist = devOutsideAssist; | |
| 85 geometry.fDevInside = devInside; | |
| 86 geometry.fDegenerate = degenerate; | |
| 87 } | |
| 88 | |
| 89 void appendAndUpdateBounds(GrColor color, const SkRect& devOutside, | |
| 90 const SkRect& devOutsideAssist, const SkRect& dev Inside, | |
| 91 bool degenerate) { | |
| 92 this->append(color, devOutside, devOutsideAssist, devInside, degenerate) ; | |
| 93 | |
| 94 SkRect bounds; | |
| 95 this->updateBounds(&bounds, fGeoData.back()); | |
| 96 this->joinBounds(bounds); | |
| 97 } | |
| 98 | |
| 99 void init() { this->updateBounds(&fBounds, fGeoData[0]); } | |
| 100 | |
| 101 private: | 147 private: |
| 102 void updateBounds(SkRect* bounds, const Geometry& geo) { | |
| 103 // If we have miterstroke then we inset devOutside and outset devOutside Assist, so we need | |
| 104 // the join for proper bounds | |
| 105 *bounds = geo.fDevOutside; | |
| 106 bounds->join(geo.fDevOutsideAssist); | |
| 107 } | |
| 108 | |
| 109 void onPrepareDraws(Target*) const override; | 148 void onPrepareDraws(Target*) const override; |
| 110 void initBatchTracker(const GrXPOverridesForBatch&) override; | 149 void initBatchTracker(const GrXPOverridesForBatch&) override; |
| 111 | 150 |
| 112 AAStrokeRectBatch(const SkMatrix& viewMatrix,bool miterStroke) | |
| 113 : INHERITED(ClassID()) { | |
|
robertphillips
2016/07/01 19:14:01
Where did the init of 'fViewMatrix' go ?
Can we re
| |
| 114 fViewMatrix = viewMatrix; | |
| 115 fMiterStroke = miterStroke; | |
| 116 } | |
| 117 | |
| 118 static const int kMiterIndexCnt = 3 * 24; | 151 static const int kMiterIndexCnt = 3 * 24; |
| 119 static const int kMiterVertexCnt = 16; | 152 static const int kMiterVertexCnt = 16; |
| 120 static const int kNumMiterRectsInIndexBuffer = 256; | 153 static const int kNumMiterRectsInIndexBuffer = 256; |
| 121 | 154 |
| 122 static const int kBevelIndexCnt = 48 + 36 + 24; | 155 static const int kBevelIndexCnt = 48 + 36 + 24; |
| 123 static const int kBevelVertexCnt = 24; | 156 static const int kBevelVertexCnt = 24; |
| 124 static const int kNumBevelRectsInIndexBuffer = 256; | 157 static const int kNumBevelRectsInIndexBuffer = 256; |
| 125 | 158 |
| 126 static const GrBuffer* GetIndexBuffer(GrResourceProvider* resourceProvider, bool miterStroke); | 159 static const GrBuffer* GetIndexBuffer(GrResourceProvider* resourceProvider, bool miterStroke); |
| 127 | 160 |
| 128 GrColor color() const { return fBatch.fColor; } | 161 GrColor color() const { return fBatch.fColor; } |
| 129 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | 162 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
| 130 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover age; } | 163 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover age; } |
| 131 bool colorIgnored() const { return fBatch.fColorIgnored; } | 164 bool colorIgnored() const { return fBatch.fColorIgnored; } |
| 132 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } | 165 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } |
| 133 const Geometry& geometry() const { return fGeoData[0]; } | |
| 134 const SkMatrix& viewMatrix() const { return fViewMatrix; } | 166 const SkMatrix& viewMatrix() const { return fViewMatrix; } |
| 135 bool miterStroke() const { return fMiterStroke; } | 167 bool miterStroke() const { return fMiterStroke; } |
| 136 | 168 |
| 137 bool onCombineIfPossible(GrBatch* t, const GrCaps&) override; | 169 bool onCombineIfPossible(GrBatch* t, const GrCaps&) override; |
| 138 | 170 |
| 139 void generateAAStrokeRectGeometry(void* vertices, | 171 void generateAAStrokeRectGeometry(void* vertices, |
| 140 size_t offset, | 172 size_t offset, |
| 141 size_t vertexStride, | 173 size_t vertexStride, |
| 142 int outerVertexNum, | 174 int outerVertexNum, |
| 143 int innerVertexNum, | 175 int innerVertexNum, |
| 144 GrColor color, | 176 GrColor color, |
| 145 const SkRect& devOutside, | 177 const SkRect& devOutside, |
| 146 const SkRect& devOutsideAssist, | 178 const SkRect& devOutsideAssist, |
| 147 const SkRect& devInside, | 179 const SkRect& devInside, |
| 148 bool miterStroke, | 180 bool miterStroke, |
| 149 bool degenerate, | 181 bool degenerate, |
| 150 bool tweakAlphaForCoverage) const; | 182 bool tweakAlphaForCoverage) const; |
| 151 | 183 |
| 152 struct BatchTracker { | 184 struct BatchTracker { |
| 153 GrColor fColor; | 185 GrColor fColor; |
| 154 bool fUsesLocalCoords; | 186 bool fUsesLocalCoords; |
| 155 bool fColorIgnored; | 187 bool fColorIgnored; |
| 156 bool fCoverageIgnored; | 188 bool fCoverageIgnored; |
| 157 bool fCanTweakAlphaForCoverage; | 189 bool fCanTweakAlphaForCoverage; |
| 158 }; | 190 }; |
| 159 | 191 |
| 192 // TODO support AA rotated stroke rects by copying around view matrices | |
| 193 struct Geometry { | |
| 194 GrColor fColor; | |
| 195 SkRect fDevOutside; | |
| 196 SkRect fDevOutsideAssist; | |
| 197 SkRect fDevInside; | |
| 198 bool fDegenerate; | |
| 199 }; | |
| 200 | |
| 160 BatchTracker fBatch; | 201 BatchTracker fBatch; |
| 161 SkSTArray<1, Geometry, true> fGeoData; | 202 SkSTArray<1, Geometry, true> fGeoData; |
| 162 SkMatrix fViewMatrix; | 203 SkMatrix fViewMatrix; |
| 163 bool fMiterStroke; | 204 bool fMiterStroke; |
| 164 | 205 |
| 165 typedef GrVertexBatch INHERITED; | 206 typedef GrVertexBatch INHERITED; |
| 166 }; | 207 }; |
| 167 | 208 |
| 168 void AAStrokeRectBatch::initBatchTracker(const GrXPOverridesForBatch& overrides) { | 209 void AAStrokeRectBatch::initBatchTracker(const GrXPOverridesForBatch& overrides) { |
| 169 // Handle any color overrides | 210 // Handle any color overrides |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 | 386 |
| 346 // In the event of two batches, one who can tweak, one who cannot, we just f all back to | 387 // In the event of two batches, one who can tweak, one who cannot, we just f all back to |
| 347 // not tweaking | 388 // not tweaking |
| 348 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) { | 389 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) { |
| 349 fBatch.fCanTweakAlphaForCoverage = false; | 390 fBatch.fCanTweakAlphaForCoverage = false; |
| 350 } | 391 } |
| 351 | 392 |
| 352 if (this->color() != that->color()) { | 393 if (this->color() != that->color()) { |
| 353 fBatch.fColor = GrColor_ILLEGAL; | 394 fBatch.fColor = GrColor_ILLEGAL; |
| 354 } | 395 } |
| 355 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); | 396 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
| 356 this->joinBounds(that->bounds()); | 397 this->joinBounds(that->bounds()); |
| 357 return true; | 398 return true; |
| 358 } | 399 } |
| 359 | 400 |
| 360 static void setup_scale(int* scale, SkScalar inset) { | 401 static void setup_scale(int* scale, SkScalar inset) { |
| 361 if (inset < SK_ScalarHalf) { | 402 if (inset < SK_ScalarHalf) { |
| 362 *scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); | 403 *scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); |
| 363 SkASSERT(*scale >= 0 && *scale <= 255); | 404 SkASSERT(*scale >= 0 && *scale <= 255); |
| 364 } else { | 405 } else { |
| 365 *scale = 0xff; | 406 *scale = 0xff; |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 for (int i = 0; i < innerVertexNum; ++i) { | 550 for (int i = 0; i < innerVertexNum; ++i) { |
| 510 if (tweakAlphaForCoverage) { | 551 if (tweakAlphaForCoverage) { |
| 511 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; | 552 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; |
| 512 } else { | 553 } else { |
| 513 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 554 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
| 514 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) = innerCoverage; | 555 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) = innerCoverage; |
| 515 } | 556 } |
| 516 } | 557 } |
| 517 } | 558 } |
| 518 | 559 |
| 519 inline static bool is_miter(const SkStrokeRec& stroke) { | |
| 520 // For hairlines, make bevel and round joins appear the same as mitered ones . | |
| 521 // small miter limit means right angles show bevel... | |
| 522 if ((stroke.getWidth() > 0) && (stroke.getJoin() != SkPaint::kMiter_Join || | |
| 523 stroke.getMiter() < SK_ScalarSqrt2)) { | |
| 524 return false; | |
| 525 } | |
| 526 return true; | |
| 527 } | |
| 528 | |
| 529 static void compute_rects(SkRect* devOutside, SkRect* devOutsideAssist, SkRect* devInside, | |
| 530 bool* isDegenerate, const SkMatrix& viewMatrix, const SkRect& rect, | |
| 531 SkScalar strokeWidth, bool miterStroke) { | |
| 532 SkRect devRect; | |
| 533 viewMatrix.mapRect(&devRect, rect); | |
| 534 | |
| 535 SkVector devStrokeSize; | |
| 536 if (strokeWidth > 0) { | |
| 537 devStrokeSize.set(strokeWidth, strokeWidth); | |
| 538 viewMatrix.mapVectors(&devStrokeSize, 1); | |
| 539 devStrokeSize.setAbs(devStrokeSize); | |
| 540 } else { | |
| 541 devStrokeSize.set(SK_Scalar1, SK_Scalar1); | |
| 542 } | |
| 543 | |
| 544 const SkScalar dx = devStrokeSize.fX; | |
| 545 const SkScalar dy = devStrokeSize.fY; | |
| 546 const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf); | |
| 547 const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf); | |
| 548 | |
| 549 *devOutside = devRect; | |
| 550 *devOutsideAssist = devRect; | |
| 551 *devInside = devRect; | |
| 552 | |
| 553 devOutside->outset(rx, ry); | |
| 554 devInside->inset(rx, ry); | |
| 555 | |
| 556 // If we have a degenerate stroking rect(ie the stroke is larger than inner rect) then we | |
| 557 // make a degenerate inside rect to avoid double hitting. We will also jam all of the points | |
| 558 // together when we render these rects. | |
| 559 SkScalar spare; | |
| 560 { | |
| 561 SkScalar w = devRect.width() - dx; | |
| 562 SkScalar h = devRect.height() - dy; | |
| 563 spare = SkTMin(w, h); | |
| 564 } | |
| 565 | |
| 566 *isDegenerate = spare <= 0; | |
| 567 if (*isDegenerate) { | |
| 568 devInside->fLeft = devInside->fRight = devRect.centerX(); | |
| 569 devInside->fTop = devInside->fBottom = devRect.centerY(); | |
| 570 } | |
| 571 | |
| 572 // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist) | |
| 573 // to draw the outside of the octagon. Because there are 8 vertices on the o uter | |
| 574 // edge, while vertex number of inner edge is 4, the same as miter-stroke. | |
| 575 if (!miterStroke) { | |
| 576 devOutside->inset(0, ry); | |
| 577 devOutsideAssist->outset(0, ry); | |
| 578 } | |
| 579 } | |
| 580 | |
| 581 namespace GrAAStrokeRectBatch { | 560 namespace GrAAStrokeRectBatch { |
| 582 | 561 |
| 583 GrDrawBatch* CreateFillBetweenRects(GrColor color, | 562 GrDrawBatch* CreateFillBetweenRects(GrColor color, |
| 584 const SkMatrix& viewMatrix, | 563 const SkMatrix& viewMatrix, |
| 585 const SkRect& devOutside, | 564 const SkRect& devOutside, |
| 586 const SkRect& devInside) { | 565 const SkRect& devInside) { |
| 587 SkASSERT(!devOutside.isEmpty()) | 566 return new AAStrokeRectBatch(color, viewMatrix, devOutside, devInside); |
| 588 SkASSERT(!devInside.isEmpty()) | |
| 589 AAStrokeRectBatch* batch = AAStrokeRectBatch::Create(viewMatrix, true); | |
| 590 batch->append(color, devOutside, devOutside, devInside, false); | |
| 591 batch->init(); | |
| 592 return batch; | |
| 593 } | 567 } |
| 594 | 568 |
| 595 GrDrawBatch* Create(GrColor color, | 569 GrDrawBatch* Create(GrColor color, |
| 596 const SkMatrix& viewMatrix, | 570 const SkMatrix& viewMatrix, |
| 597 const SkRect& rect, | 571 const SkRect& rect, |
| 598 const SkStrokeRec& stroke) { | 572 const SkStrokeRec& stroke) { |
| 599 bool isMiterStroke = is_miter(stroke); | 573 return new AAStrokeRectBatch(color, viewMatrix, rect, stroke); |
| 600 AAStrokeRectBatch* batch = AAStrokeRectBatch::Create(viewMatrix, isMiterStro ke); | |
| 601 | |
| 602 SkRect devOutside, devOutsideAssist, devInside; | |
| 603 bool isDegenerate; | |
| 604 compute_rects(&devOutside, &devOutsideAssist, &devInside, &isDegenerate, vie wMatrix, | |
| 605 rect, stroke.getWidth(), isMiterStroke); | |
| 606 | |
| 607 batch->append(color, devOutside, devOutsideAssist, devInside, isDegenerate); | |
| 608 batch->init(); | |
| 609 return batch; | |
| 610 } | 574 } |
| 611 | 575 |
| 612 bool Append(GrBatch* origBatch, | |
| 613 GrColor color, | |
| 614 const SkMatrix& viewMatrix, | |
| 615 const SkRect& rect, | |
| 616 const SkStrokeRec& stroke) { | |
| 617 AAStrokeRectBatch* batch = origBatch->cast<AAStrokeRectBatch>(); | |
| 618 | |
| 619 // we can't batch across vm changes | |
| 620 bool isMiterStroke = is_miter(stroke); | |
| 621 if (!batch->canAppend(viewMatrix, isMiterStroke)) { | |
| 622 return false; | |
| 623 } | |
| 624 | |
| 625 SkRect devOutside, devOutsideAssist, devInside; | |
| 626 bool isDegenerate; | |
| 627 compute_rects(&devOutside, &devOutsideAssist, &devInside, &isDegenerate, vie wMatrix, | |
| 628 rect, stroke.getWidth(), isMiterStroke); | |
| 629 | |
| 630 batch->appendAndUpdateBounds(color, devOutside, devOutsideAssist, devInside, isDegenerate); | |
| 631 return true; | |
| 632 } | 576 } |
| 633 | 577 |
| 634 }; | |
| 635 | |
| 636 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 578 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
| 637 | 579 |
| 638 #ifdef GR_TEST_UTILS | 580 #ifdef GR_TEST_UTILS |
| 639 | 581 |
| 640 #include "GrBatchTest.h" | 582 #include "GrBatchTest.h" |
| 641 | 583 |
| 642 DRAW_BATCH_TEST_DEFINE(AAStrokeRectBatch) { | 584 DRAW_BATCH_TEST_DEFINE(AAStrokeRectBatch) { |
| 643 bool miterStroke = random->nextBool(); | 585 bool miterStroke = random->nextBool(); |
| 644 | 586 |
| 645 // Create either a empty rect or a non-empty rect. | 587 // Create either a empty rect or a non-empty rect. |
| 646 SkRect rect = random->nextBool() ? SkRect::MakeXYWH(10, 10, 50, 40) : | 588 SkRect rect = random->nextBool() ? SkRect::MakeXYWH(10, 10, 50, 40) : |
| 647 SkRect::MakeXYWH(6, 7, 0, 0); | 589 SkRect::MakeXYWH(6, 7, 0, 0); |
| 648 SkScalar minDim = SkMinScalar(rect.width(), rect.height()); | 590 SkScalar minDim = SkMinScalar(rect.width(), rect.height()); |
| 649 SkScalar strokeWidth = random->nextUScalar1() * minDim; | 591 SkScalar strokeWidth = random->nextUScalar1() * minDim; |
| 650 | 592 |
| 651 GrColor color = GrRandomColor(random); | 593 GrColor color = GrRandomColor(random); |
| 652 | 594 |
| 653 SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); | 595 SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); |
| 654 rec.setStrokeStyle(strokeWidth); | 596 rec.setStrokeStyle(strokeWidth); |
| 655 rec.setStrokeParams(SkPaint::kButt_Cap, | 597 rec.setStrokeParams(SkPaint::kButt_Cap, |
| 656 miterStroke ? SkPaint::kMiter_Join : SkPaint::kBevel_Joi n, | 598 miterStroke ? SkPaint::kMiter_Join : SkPaint::kBevel_Joi n, |
| 657 1.f); | 599 1.f); |
| 658 SkMatrix matrix = GrTest::TestMatrixRectStaysRect(random); | 600 SkMatrix matrix = GrTest::TestMatrixRectStaysRect(random); |
| 659 return GrAAStrokeRectBatch::Create(color, matrix, rect, rec); | 601 return GrAAStrokeRectBatch::Create(color, matrix, rect, rec); |
| 660 } | 602 } |
| 661 | 603 |
| 662 #endif | 604 #endif |
| OLD | NEW |