1c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth/* 2c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth * Copyright 2016 Google Inc. 3c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth * 4c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth * Use of this source code is governed by a BSD-style license that can be 5c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth * found in the LICENSE file. 6c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth */ 7c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 8fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon#include "GrShadowRRectOp.h" 9c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 105ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon#include "GrDrawOpTest.h" 11742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h" 12c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth#include "GrResourceProvider.h" 13c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth#include "GrStyle.h" 14c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 15c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth#include "effects/GrShadowGeoProc.h" 16c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 17c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth/////////////////////////////////////////////////////////////////////////////// 18c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 19c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// We have two possible cases for geometry for a circle: 20c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 21c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// In the case of a normal fill, we draw geometry for the circle as an octagon. 22c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const uint16_t gFillCircleIndices[] = { 23fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // enter the octagon 24fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // clang-format off 25fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 0, 1, 8, 1, 2, 8, 26fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 2, 3, 8, 3, 4, 8, 27fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 4, 5, 8, 5, 6, 8, 28fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 6, 7, 8, 7, 0, 8, 29fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // clang-format on 30c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth}; 31c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 32c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// For stroked circles, we use two nested octagons. 33c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const uint16_t gStrokeCircleIndices[] = { 34fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // enter the octagon 35fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // clang-format off 36fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 0, 1, 9, 0, 9, 8, 37fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 1, 2, 10, 1, 10, 9, 38fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 2, 3, 11, 2, 11, 10, 39fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 3, 4, 12, 3, 12, 11, 40fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 4, 5, 13, 4, 13, 12, 41fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 5, 6, 14, 5, 14, 13, 42fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 6, 7, 15, 6, 15, 14, 43fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 7, 0, 8, 7, 8, 15, 44fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // clang-format on 45c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth}; 46c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 47c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const int kIndicesPerFillCircle = SK_ARRAY_COUNT(gFillCircleIndices); 48c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const int kIndicesPerStrokeCircle = SK_ARRAY_COUNT(gStrokeCircleIndices); 49c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const int kVertsPerStrokeCircle = 16; 50c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const int kVertsPerFillCircle = 9; 51c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 52c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic int circle_type_to_vert_count(bool stroked) { 53c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return stroked ? kVertsPerStrokeCircle : kVertsPerFillCircle; 54c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 55c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 56c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic int circle_type_to_index_count(bool stroked) { 57c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return stroked ? kIndicesPerStrokeCircle : kIndicesPerFillCircle; 58c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 59c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 60c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const uint16_t* circle_type_to_indices(bool stroked) { 61c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return stroked ? gStrokeCircleIndices : gFillCircleIndices; 62c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 63c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 64c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth/////////////////////////////////////////////////////////////////////////////// 65c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 66fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomonclass ShadowCircleOp final : public GrMeshDrawOp { 67c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthpublic: 6825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 69c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 70649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon static std::unique_ptr<GrMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix, 71649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkPoint center, SkScalar radius, SkScalar blurRadius, 72649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const GrStyle& style) { 73c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(viewMatrix.isSimilarity()); 74c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const SkStrokeRec& stroke = style.strokeRec(); 75c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (style.hasPathEffect()) { 76c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return nullptr; 77c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 78c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkStrokeRec::Style recStyle = stroke.getStyle(); 79c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 80c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth viewMatrix.mapPoints(¢er, 1); 81c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth radius = viewMatrix.mapRadius(radius); 82c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); 83c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 84fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon bool isStrokeOnly = 85fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkStrokeRec::kStroke_Style == recStyle || SkStrokeRec::kHairline_Style == recStyle; 86c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == recStyle; 87c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 88c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar innerRadius = -SK_ScalarHalf; 89c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar outerRadius = radius; 90c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar halfWidth = 0; 91c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (hasStroke) { 92c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (SkScalarNearlyZero(strokeWidth)) { 93c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth halfWidth = SK_ScalarHalf; 94c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } else { 95c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth halfWidth = SkScalarHalf(strokeWidth); 96c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 97c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 98c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth outerRadius += halfWidth; 99c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (isStrokeOnly) { 100c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth innerRadius = radius - halfWidth; 101c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 102c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 103c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 104c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth bool stroked = isStrokeOnly && innerRadius > 0.0f; 105f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon std::unique_ptr<ShadowCircleOp> op(new ShadowCircleOp()); 106fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon op->fViewMatrixIfUsingLocalCoords = viewMatrix; 107c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 108c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkRect devBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius, 109c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth center.fX + outerRadius, center.fY + outerRadius); 110c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 11192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon op->fCircles.emplace_back( 11292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon Circle{color, outerRadius, innerRadius, blurRadius, devBounds, stroked}); 113c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 114c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Use the original radius and stroke radius for the bounds so that it does not include the 115c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // AA bloat. 116c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth radius += halfWidth; 117fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon op->setBounds( 118fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon {center.fX - radius, center.fY - radius, center.fX + radius, center.fY + radius}, 119fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon HasAABloat::kNo, IsZeroArea::kNo); 120fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon op->fVertCount = circle_type_to_vert_count(stroked); 121fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon op->fIndexCount = circle_type_to_index_count(stroked); 122fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return std::move(op); 123c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 124c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 125fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon const char* name() const override { return "ShadowCircleOp"; } 126c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 127c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkString dumpInfo() const override { 128c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkString string; 12992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon for (int i = 0; i < fCircles.count(); ++i) { 130fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon string.appendf( 131fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], " 132fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon "OuterRad: %.2f, InnerRad: %.2f, BlurRad: %.2f\n", 13392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon fCircles[i].fColor, fCircles[i].fDevBounds.fLeft, fCircles[i].fDevBounds.fTop, 13492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon fCircles[i].fDevBounds.fRight, fCircles[i].fDevBounds.fBottom, 13592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon fCircles[i].fOuterRadius, fCircles[i].fInnerRadius, fCircles[i].fBlurRadius); 136c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 1377c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(DumpPipelineInfo(*this->pipeline())); 138c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth string.append(INHERITED::dumpInfo()); 139c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return string; 140c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 141c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 142c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthprivate: 143fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ShadowCircleOp() : INHERITED(ClassID()) {} 14492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 145c0b642ca48d58416409e555549434066f09692b7Brian Salomon void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 146c0b642ca48d58416409e555549434066f09692b7Brian Salomon GrPipelineAnalysisCoverage* coverage) const override { 147c0b642ca48d58416409e555549434066f09692b7Brian Salomon color->setToConstant(fCircles[0].fColor); 148c0b642ca48d58416409e555549434066f09692b7Brian Salomon *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 14992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 15092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 15192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 15292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon optimizations.getOverrideColorIfSet(&fCircles[0].fColor); 15392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon if (!optimizations.readsLocalCoords()) { 154c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fViewMatrixIfUsingLocalCoords.reset(); 155c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 156c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 157c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 158c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth void onPrepareDraws(Target* target) const override { 159c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkMatrix localMatrix; 160c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 161c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return; 162c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 163c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 164c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Setup geometry processor 165c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth sk_sp<GrGeometryProcessor> gp(GrRRectShadowGeoProc::Make(localMatrix)); 166c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 167c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth struct CircleVertex { 168fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkPoint fPos; 169fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon GrColor fColor; 170fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkPoint fOffset; 171c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fOuterRadius; 172c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fBlurRadius; 173c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth }; 174c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 17592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon int instanceCount = fCircles.count(); 176c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth size_t vertexStride = gp->getVertexStride(); 177c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(vertexStride == sizeof(CircleVertex)); 178c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 179c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const GrBuffer* vertexBuffer; 180c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth int firstVertex; 181fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon char* vertices = (char*)target->makeVertexSpace(vertexStride, fVertCount, &vertexBuffer, 182fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon &firstVertex); 183c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!vertices) { 184c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkDebugf("Could not allocate vertices\n"); 185c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return; 186c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 187c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 188c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const GrBuffer* indexBuffer = nullptr; 189c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth int firstIndex = 0; 190c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth uint16_t* indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex); 191c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!indices) { 192c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkDebugf("Could not allocate indices\n"); 193c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return; 194c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 195c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 196c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth int currStartVertex = 0; 197c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth for (int i = 0; i < instanceCount; i++) { 19892aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon const Circle& circle = fCircles[i]; 199c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 20092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon GrColor color = circle.fColor; 20192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon SkScalar outerRadius = circle.fOuterRadius; 20292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon SkScalar innerRadius = circle.fInnerRadius; 20392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon SkScalar blurRadius = circle.fBlurRadius; 204c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 20592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon const SkRect& bounds = circle.fDevBounds; 206c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* ov0 = reinterpret_cast<CircleVertex*>(vertices + 0 * vertexStride); 207c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* ov1 = reinterpret_cast<CircleVertex*>(vertices + 1 * vertexStride); 208c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* ov2 = reinterpret_cast<CircleVertex*>(vertices + 2 * vertexStride); 209c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* ov3 = reinterpret_cast<CircleVertex*>(vertices + 3 * vertexStride); 210c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* ov4 = reinterpret_cast<CircleVertex*>(vertices + 4 * vertexStride); 211c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* ov5 = reinterpret_cast<CircleVertex*>(vertices + 5 * vertexStride); 212c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* ov6 = reinterpret_cast<CircleVertex*>(vertices + 6 * vertexStride); 213c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* ov7 = reinterpret_cast<CircleVertex*>(vertices + 7 * vertexStride); 214c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 215c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // The inner radius in the vertex data must be specified in normalized space. 216c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth innerRadius = innerRadius / outerRadius; 21760c05f98aa22d89e4ef25acb4799936f5df3cff2Herb Derby 218c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkPoint center = SkPoint::Make(bounds.centerX(), bounds.centerY()); 219fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkScalar halfWidth = 0.5f * bounds.width(); 220c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar octOffset = 0.41421356237f; // sqrt(2) - 1 221c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 222fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ov0->fPos = center + SkPoint::Make(-octOffset * halfWidth, -halfWidth); 223c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov0->fColor = color; 224c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov0->fOffset = SkPoint::Make(-octOffset, -1); 225c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov0->fOuterRadius = outerRadius; 226c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov0->fBlurRadius = blurRadius; 227c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 228fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ov1->fPos = center + SkPoint::Make(octOffset * halfWidth, -halfWidth); 229c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov1->fColor = color; 230c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov1->fOffset = SkPoint::Make(octOffset, -1); 231c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov1->fOuterRadius = outerRadius; 232c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov1->fBlurRadius = blurRadius; 233c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 234fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ov2->fPos = center + SkPoint::Make(halfWidth, -octOffset * halfWidth); 235c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov2->fColor = color; 236c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov2->fOffset = SkPoint::Make(1, -octOffset); 237c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov2->fOuterRadius = outerRadius; 238c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov2->fBlurRadius = blurRadius; 239c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 240fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ov3->fPos = center + SkPoint::Make(halfWidth, octOffset * halfWidth); 241c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov3->fColor = color; 242c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov3->fOffset = SkPoint::Make(1, octOffset); 243c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov3->fOuterRadius = outerRadius; 244c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov3->fBlurRadius = blurRadius; 245c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 246fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ov4->fPos = center + SkPoint::Make(octOffset * halfWidth, halfWidth); 247c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov4->fColor = color; 248c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov4->fOffset = SkPoint::Make(octOffset, 1); 249c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov4->fOuterRadius = outerRadius; 250c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov4->fBlurRadius = blurRadius; 251c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 252fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ov5->fPos = center + SkPoint::Make(-octOffset * halfWidth, halfWidth); 253c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov5->fColor = color; 254c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov5->fOffset = SkPoint::Make(-octOffset, 1); 255c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov5->fOuterRadius = outerRadius; 256c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov5->fBlurRadius = blurRadius; 257c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 258fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ov6->fPos = center + SkPoint::Make(-halfWidth, octOffset * halfWidth); 259c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov6->fColor = color; 260c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov6->fOffset = SkPoint::Make(-1, octOffset); 261c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov6->fOuterRadius = outerRadius; 262c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov6->fBlurRadius = blurRadius; 263c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 264fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ov7->fPos = center + SkPoint::Make(-halfWidth, -octOffset * halfWidth); 265c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov7->fColor = color; 266c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov7->fOffset = SkPoint::Make(-1, -octOffset); 267c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov7->fOuterRadius = outerRadius; 268c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth ov7->fBlurRadius = blurRadius; 269c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 27092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon if (circle.fStroked) { 271c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // compute the inner ring 272c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv0 = reinterpret_cast<CircleVertex*>(vertices + 8 * vertexStride); 273c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv1 = reinterpret_cast<CircleVertex*>(vertices + 9 * vertexStride); 274c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv2 = reinterpret_cast<CircleVertex*>(vertices + 10 * vertexStride); 275c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv3 = reinterpret_cast<CircleVertex*>(vertices + 11 * vertexStride); 276c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv4 = reinterpret_cast<CircleVertex*>(vertices + 12 * vertexStride); 277c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv5 = reinterpret_cast<CircleVertex*>(vertices + 13 * vertexStride); 278c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv6 = reinterpret_cast<CircleVertex*>(vertices + 14 * vertexStride); 279c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv7 = reinterpret_cast<CircleVertex*>(vertices + 15 * vertexStride); 280c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 281c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // cosine and sine of pi/8 282c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar c = 0.923579533f; 283c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar s = 0.382683432f; 28492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon SkScalar r = circle.fInnerRadius; 285c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 286fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv0->fPos = center + SkPoint::Make(-s * r, -c * r); 287c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv0->fColor = color; 288fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv0->fOffset = SkPoint::Make(-s * innerRadius, -c * innerRadius); 289c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv0->fOuterRadius = outerRadius; 290c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv0->fBlurRadius = blurRadius; 291c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 292fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv1->fPos = center + SkPoint::Make(s * r, -c * r); 293c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv1->fColor = color; 294fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv1->fOffset = SkPoint::Make(s * innerRadius, -c * innerRadius); 295c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv1->fOuterRadius = outerRadius; 296c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv1->fBlurRadius = blurRadius; 297c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 298fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv2->fPos = center + SkPoint::Make(c * r, -s * r); 299c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv2->fColor = color; 300fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv2->fOffset = SkPoint::Make(c * innerRadius, -s * innerRadius); 301c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv2->fOuterRadius = outerRadius; 302c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv2->fBlurRadius = blurRadius; 303c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 304fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv3->fPos = center + SkPoint::Make(c * r, s * r); 305c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv3->fColor = color; 306fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv3->fOffset = SkPoint::Make(c * innerRadius, s * innerRadius); 307c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv3->fOuterRadius = outerRadius; 308c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv3->fBlurRadius = blurRadius; 309c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 310fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv4->fPos = center + SkPoint::Make(s * r, c * r); 311c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv4->fColor = color; 312fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv4->fOffset = SkPoint::Make(s * innerRadius, c * innerRadius); 313c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv4->fOuterRadius = outerRadius; 314c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv4->fBlurRadius = blurRadius; 315c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 316fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv5->fPos = center + SkPoint::Make(-s * r, c * r); 317c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv5->fColor = color; 318fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv5->fOffset = SkPoint::Make(-s * innerRadius, c * innerRadius); 319c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv5->fOuterRadius = outerRadius; 320c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv5->fBlurRadius = blurRadius; 321c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 322fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv6->fPos = center + SkPoint::Make(-c * r, s * r); 323c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv6->fColor = color; 324fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv6->fOffset = SkPoint::Make(-c * innerRadius, s * innerRadius); 325c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv6->fOuterRadius = outerRadius; 326c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv6->fBlurRadius = blurRadius; 327c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 328fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv7->fPos = center + SkPoint::Make(-c * r, -s * r); 329c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv7->fColor = color; 330fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon iv7->fOffset = SkPoint::Make(-c * innerRadius, -s * innerRadius); 331c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv7->fOuterRadius = outerRadius; 332c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv7->fBlurRadius = blurRadius; 333c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } else { 334c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // filled 335c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* iv = reinterpret_cast<CircleVertex*>(vertices + 8 * vertexStride); 336c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv->fPos = center; 337c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv->fColor = color; 338c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv->fOffset = SkPoint::Make(0, 0); 339c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv->fOuterRadius = outerRadius; 340c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth iv->fBlurRadius = blurRadius; 341c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 342c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 34392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon const uint16_t* primIndices = circle_type_to_indices(circle.fStroked); 34492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon const int primIndexCount = circle_type_to_index_count(circle.fStroked); 345c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth for (int i = 0; i < primIndexCount; ++i) { 346c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth *indices++ = primIndices[i] + currStartVertex; 347c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 348c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 34992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon currStartVertex += circle_type_to_vert_count(circle.fStroked); 35092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon vertices += circle_type_to_vert_count(circle.fStroked) * vertexStride; 351c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 352c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 353c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth GrMesh mesh; 354c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, 355c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth firstIndex, fVertCount, fIndexCount); 356c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth target->draw(gp.get(), mesh); 357c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 358c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 35925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 360fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ShadowCircleOp* that = t->cast<ShadowCircleOp>(); 361c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 362c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth that->bounds(), caps)) { 363c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return false; 364c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 365c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 366c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) { 367c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return false; 368c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 369c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 37092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon fCircles.push_back_n(that->fCircles.count(), that->fCircles.begin()); 371c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth this->joinBounds(*that); 372c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fVertCount += that->fVertCount; 373c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fIndexCount += that->fIndexCount; 374c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return true; 375c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 376c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 37792aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon struct Circle { 378fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon GrColor fColor; 379c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fOuterRadius; 380c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fInnerRadius; 381c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fBlurRadius; 382fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkRect fDevBounds; 383fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon bool fStroked; 384c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth }; 385c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 38692aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon SkSTArray<1, Circle, true> fCircles; 387fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkMatrix fViewMatrixIfUsingLocalCoords; 388fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon int fVertCount; 389fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon int fIndexCount; 390c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 391dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon typedef GrMeshDrawOp INHERITED; 392c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth}; 393c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 394c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth/////////////////////////////////////////////////////////////////////////////////////////////////// 395c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 396c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// We have two possible cases for geometry for a shadow roundrect. 397c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// 398c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// In the case of a normal stroke, we draw the roundrect as a 9-patch without the center quad. 399c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// ____________ 400c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// |_|________|_| 401c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// | | | | 402c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// | | | | 403c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// | | | | 404c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// |_|________|_| 405c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// |_|________|_| 406c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// 407c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// In the case where the stroke width is greater than twice the corner radius (overstroke), 408c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// we add additional geometry to mark out the rectangle in the center. The shared vertices 409c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// are duplicated so we can set a different outer radius for the fill calculation. 410c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// ____________ 411c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// |_|________|_| 412c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// | |\ ____ /| | 413c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// | | | | | | 414c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// | | |____| | | 415c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// |_|/______\|_| 416c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// |_|________|_| 417c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// 418c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// For filled rrects we reuse the overstroke geometry but make the inner rect degenerate 419c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// (either a point or a horizontal or vertical line). 420c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 421c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const uint16_t gOverstrokeRRectIndices[] = { 422fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // clang-format off 423fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // corners 424fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 0, 1, 5, 0, 5, 4, 425fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 2, 3, 7, 2, 7, 6, 426fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 8, 9, 13, 8, 13, 12, 427fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 10, 11, 15, 10, 15, 14, 428fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 429fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // edges 430fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 1, 2, 6, 1, 6, 5, 431fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 4, 5, 9, 4, 9, 8, 432fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 6, 7, 11, 6, 11, 10, 433fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 9, 10, 14, 9, 14, 13, 434fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 435fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // overstroke quads 436fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // we place this at the end so that we can skip these indices when rendering as stroked 437fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 16, 17, 19, 16, 19, 18, 438fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 19, 17, 23, 19, 23, 21, 439fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 21, 23, 22, 21, 22, 20, 440fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon 22, 16, 18, 22, 18, 20, 441fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon // clang-format on 442c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth}; 443c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// standard stroke indices start at the same place, but will skip the overstroke "ring" 444c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const uint16_t* gStrokeRRectIndices = gOverstrokeRRectIndices; 445c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 446c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// overstroke count 447c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const int kIndicesPerOverstrokeRRect = SK_ARRAY_COUNT(gOverstrokeRRectIndices); 448c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// simple stroke count skips overstroke indices 449c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const int kIndicesPerStrokeRRect = kIndicesPerOverstrokeRRect - 6 * 4 + 6; 450c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const int kVertsPerStrokeRRect = 16; 451c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const int kVertsPerOverstrokeRRect = 24; 452c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 453c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthenum RRectType { 454c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth kFill_RRectType, 455c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth kStroke_RRectType, 456c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth kOverstroke_RRectType, 457c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth}; 458c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 459c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic int rrect_type_to_vert_count(RRectType type) { 460fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon switch (type) { 461fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kFill_RRectType: 462fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return kVertsPerOverstrokeRRect; 463fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kStroke_RRectType: 464fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return kVertsPerStrokeRRect; 465fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kOverstroke_RRectType: 466fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return kVertsPerOverstrokeRRect; 467fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon } 468fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkFAIL("Invalid type"); 469fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return 0; 470c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 471c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 472c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic int rrect_type_to_index_count(RRectType type) { 473fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon switch (type) { 474fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kFill_RRectType: 475fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return kIndicesPerOverstrokeRRect; 476fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kStroke_RRectType: 477fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return kIndicesPerStrokeRRect; 478fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kOverstroke_RRectType: 479fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return kIndicesPerOverstrokeRRect; 480fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon } 481fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkFAIL("Invalid type"); 482fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return 0; 483c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 484c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 485c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthstatic const uint16_t* rrect_type_to_indices(RRectType type) { 486fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon switch (type) { 487fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kFill_RRectType: 488fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return gOverstrokeRRectIndices; 489fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kStroke_RRectType: 490fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return gStrokeRRectIndices; 491fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon case kOverstroke_RRectType: 492fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return gOverstrokeRRectIndices; 493fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon } 494fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkFAIL("Invalid type"); 495fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return nullptr; 496c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 497c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 498c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// For distance computations in the interior of filled rrects we: 499c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// 500c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// add a interior degenerate (point or line) rect 501c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// each vertex of that rect gets -outerRad as its radius 502c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// this makes the computation of the distance to the outer edge be negative 503c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// negative values are caught and then handled differently in the GP's onEmitCode 504c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// each vertex is also given the normalized x & y distance from the interior rect's edge 505c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth// the GP takes the min of those depths +1 to get the normalized distance to the outer edge 506c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 507fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomonclass ShadowCircularRRectOp final : public GrMeshDrawOp { 508c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verthpublic: 50925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 510c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 511c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then strokeOnly indicates 512c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // whether the rrect is only stroked or stroked and filled. 513fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ShadowCircularRRectOp(GrColor color, const SkMatrix& viewMatrix, const SkRect& devRect, 514fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon float devRadius, float blurRadius, float devStrokeWidth, bool strokeOnly) 515fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon : INHERITED(ClassID()), fViewMatrixIfUsingLocalCoords(viewMatrix) { 516c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkRect bounds = devRect; 517c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(!(devStrokeWidth <= 0 && strokeOnly)); 518c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar innerRadius = 0.0f; 519c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar outerRadius = devRadius; 520c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar halfWidth = 0; 521c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth RRectType type = kFill_RRectType; 522c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (devStrokeWidth > 0) { 523c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (SkScalarNearlyZero(devStrokeWidth)) { 524c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth halfWidth = SK_ScalarHalf; 525c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } else { 526c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth halfWidth = SkScalarHalf(devStrokeWidth); 527c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 528c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 529c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (strokeOnly) { 530c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // If stroke is greater than width or height, this is still a fill 531c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Otherwise we compute stroke params 532fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon if (devStrokeWidth <= devRect.width() && devStrokeWidth <= devRect.height()) { 533c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth innerRadius = devRadius - halfWidth; 534c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth type = (innerRadius >= 0) ? kStroke_RRectType : kOverstroke_RRectType; 535c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 536c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 537c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth outerRadius += halfWidth; 538c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth bounds.outset(halfWidth, halfWidth); 539c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 540c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 541cf40e307cd7c78c3ac8812229a7f4f2796b8688eJim Van Verth this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo); 542c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 543c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fGeoData.emplace_back(Geometry{color, outerRadius, innerRadius, blurRadius, bounds, type}); 544c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fVertCount = rrect_type_to_vert_count(type); 545c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fIndexCount = rrect_type_to_index_count(type); 546c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 547c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 548fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon const char* name() const override { return "ShadowCircularRRectOp"; } 549c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 550c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkString dumpInfo() const override { 551c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkString string; 552c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth for (int i = 0; i < fGeoData.count(); ++i) { 553fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon string.appendf( 554fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]," 555fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon "OuterRad: %.2f, InnerRad: %.2f, BlurRad: %.2f\n", 556fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon fGeoData[i].fColor, fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds.fTop, 557fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds.fBottom, 558fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon fGeoData[i].fOuterRadius, fGeoData[i].fInnerRadius, fGeoData[i].fBlurRadius); 559c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 5607c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(DumpPipelineInfo(*this->pipeline())); 561c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth string.append(INHERITED::dumpInfo()); 562c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return string; 563c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 564c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 56592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomonprivate: 566c0b642ca48d58416409e555549434066f09692b7Brian Salomon void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 567c0b642ca48d58416409e555549434066f09692b7Brian Salomon GrPipelineAnalysisCoverage* coverage) const override { 568c0b642ca48d58416409e555549434066f09692b7Brian Salomon color->setToConstant(fGeoData[0].fColor); 569c0b642ca48d58416409e555549434066f09692b7Brian Salomon *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 570c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 571c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 57292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 57392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon optimizations.getOverrideColorIfSet(&fGeoData[0].fColor); 57492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon if (!optimizations.readsLocalCoords()) { 575c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fViewMatrixIfUsingLocalCoords.reset(); 576c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 577c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 578c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 579c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth struct CircleVertex { 580fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkPoint fPos; 581fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon GrColor fColor; 582fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkPoint fOffset; 583c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fOuterRadius; 584c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fBlurRadius; 585c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth }; 586c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 587fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon static void FillInOverstrokeVerts(CircleVertex** verts, const SkRect& bounds, SkScalar smInset, 588fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkScalar bigInset, SkScalar xOffset, SkScalar outerRadius, 589fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon GrColor color, SkScalar blurRadius) { 590c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(smInset < bigInset); 591c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 592c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // TL 593c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fPos = SkPoint::Make(bounds.fLeft + smInset, bounds.fTop + smInset); 594c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fColor = color; 595c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOffset = SkPoint::Make(xOffset, 0); 596c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOuterRadius = outerRadius; 597c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fBlurRadius = blurRadius; 598c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)++; 599c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 600c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // TR 601c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fPos = SkPoint::Make(bounds.fRight - smInset, bounds.fTop + smInset); 602c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fColor = color; 603c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOffset = SkPoint::Make(xOffset, 0); 604c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOuterRadius = outerRadius; 605c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fBlurRadius = blurRadius; 606c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)++; 607c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 608c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fPos = SkPoint::Make(bounds.fLeft + bigInset, bounds.fTop + bigInset); 609c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fColor = color; 610c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOffset = SkPoint::Make(0, 0); 611c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOuterRadius = outerRadius; 612c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fBlurRadius = blurRadius; 613c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)++; 614c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 615c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fPos = SkPoint::Make(bounds.fRight - bigInset, bounds.fTop + bigInset); 616c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fColor = color; 617c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOffset = SkPoint::Make(0, 0); 618c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOuterRadius = outerRadius; 619c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fBlurRadius = blurRadius; 620c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)++; 621c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 622c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fPos = SkPoint::Make(bounds.fLeft + bigInset, bounds.fBottom - bigInset); 623c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fColor = color; 624c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOffset = SkPoint::Make(0, 0); 625c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOuterRadius = outerRadius; 626c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fBlurRadius = blurRadius; 627c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)++; 628c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 629c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fPos = SkPoint::Make(bounds.fRight - bigInset, bounds.fBottom - bigInset); 630c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fColor = color; 631c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOffset = SkPoint::Make(0, 0); 632c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOuterRadius = outerRadius; 633c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fBlurRadius = blurRadius; 634c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)++; 635c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 636c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // BL 637c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fPos = SkPoint::Make(bounds.fLeft + smInset, bounds.fBottom - smInset); 638c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fColor = color; 639c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOffset = SkPoint::Make(xOffset, 0); 640c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOuterRadius = outerRadius; 641c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fBlurRadius = blurRadius; 642c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)++; 643c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 644c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // BR 645c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fPos = SkPoint::Make(bounds.fRight - smInset, bounds.fBottom - smInset); 646c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fColor = color; 647c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOffset = SkPoint::Make(xOffset, 0); 648c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fOuterRadius = outerRadius; 649c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)->fBlurRadius = blurRadius; 650c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth (*verts)++; 651c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 652c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 653c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth void onPrepareDraws(Target* target) const override { 654c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Invert the view matrix as a local matrix (if any other processors require coords). 655c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkMatrix localMatrix; 656c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 657c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return; 658c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 659c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 660c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Setup geometry processor 661c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth sk_sp<GrGeometryProcessor> gp(GrRRectShadowGeoProc::Make(localMatrix)); 662c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 663c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth int instanceCount = fGeoData.count(); 664c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth size_t vertexStride = gp->getVertexStride(); 665c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(sizeof(CircleVertex) == vertexStride); 666c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 667c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const GrBuffer* vertexBuffer; 668c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth int firstVertex; 669c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 670c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth CircleVertex* verts = (CircleVertex*)target->makeVertexSpace(vertexStride, fVertCount, 671c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth &vertexBuffer, &firstVertex); 672c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!verts) { 673c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkDebugf("Could not allocate vertices\n"); 674c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return; 675c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 676c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 677c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const GrBuffer* indexBuffer = nullptr; 678c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth int firstIndex = 0; 679c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth uint16_t* indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex); 680c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!indices) { 681c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkDebugf("Could not allocate indices\n"); 682c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return; 683c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 684c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 685c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth int currStartVertex = 0; 686c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth for (int i = 0; i < instanceCount; i++) { 687c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const Geometry& args = fGeoData[i]; 688c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 689c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth GrColor color = args.fColor; 690c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar outerRadius = args.fOuterRadius; 691c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 692c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const SkRect& bounds = args.fDevBounds; 693c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 694fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkScalar yCoords[4] = {bounds.fTop, bounds.fTop + outerRadius, 695fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon bounds.fBottom - outerRadius, bounds.fBottom}; 696c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 697fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkScalar yOuterRadii[4] = {-1, 0, 0, 1}; 698c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // The inner radius in the vertex data must be specified in normalized space. 699c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // For fills, specifying -1/outerRadius guarantees an alpha of 1.0 at the inner radius. 700c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar blurRadius = args.fBlurRadius; 701c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth for (int i = 0; i < 4; ++i) { 702c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); 703c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fColor = color; 704c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fOffset = SkPoint::Make(-1, yOuterRadii[i]); 705c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fOuterRadius = outerRadius; 706c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fBlurRadius = blurRadius; 707c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts++; 708c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 709c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[i]); 710c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fColor = color; 711c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); 712c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fOuterRadius = outerRadius; 713c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fBlurRadius = blurRadius; 714c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts++; 715c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 716c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords[i]); 717c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fColor = color; 718c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); 719c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fOuterRadius = outerRadius; 720c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fBlurRadius = blurRadius; 721c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts++; 722c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 723c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); 724c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fColor = color; 725c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fOffset = SkPoint::Make(1, yOuterRadii[i]); 726c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fOuterRadius = outerRadius; 727c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts->fBlurRadius = blurRadius; 728c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth verts++; 729c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 730c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Add the additional vertices for overstroked rrects. 731c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Effectively this is an additional stroked rrect, with its 732c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // outer radius = outerRadius - innerRadius, and inner radius = 0. 733c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // This will give us correct AA in the center and the correct 734c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // distance to the outer edge. 735c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // 736c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Also, the outer offset is a constant vector pointing to the right, which 737c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // guarantees that the distance value along the outer rectangle is constant. 738c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (kOverstroke_RRectType == args.fType) { 739c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(args.fInnerRadius <= 0.0f); 740c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 741c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar overstrokeOuterRadius = outerRadius - args.fInnerRadius; 742c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // this is the normalized distance from the outer rectangle of this 743c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // geometry to the outer edge 744c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar maxOffset = -args.fInnerRadius / overstrokeOuterRadius; 745c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 746fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon FillInOverstrokeVerts(&verts, bounds, outerRadius, overstrokeOuterRadius, maxOffset, 747fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon overstrokeOuterRadius, color, blurRadius); 748c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 749c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 750c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (kFill_RRectType == args.fType) { 751c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar halfMinDim = 0.5f * SkTMin(bounds.width(), bounds.height()); 752c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 753c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar xOffset = 1.0f - outerRadius / halfMinDim; 754c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 755fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon FillInOverstrokeVerts(&verts, bounds, outerRadius, halfMinDim, xOffset, halfMinDim, 756fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon color, blurRadius); 757c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 758c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 759c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const uint16_t* primIndices = rrect_type_to_indices(args.fType); 760c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const int primIndexCount = rrect_type_to_index_count(args.fType); 761c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth for (int i = 0; i < primIndexCount; ++i) { 762c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth *indices++ = primIndices[i] + currStartVertex; 763c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 764c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 765c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth currStartVertex += rrect_type_to_vert_count(args.fType); 766c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 767c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 768c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth GrMesh mesh; 769c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, 770c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth firstIndex, fVertCount, fIndexCount); 771c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth target->draw(gp.get(), mesh); 772c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 773c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 77425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 775fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon ShadowCircularRRectOp* that = t->cast<ShadowCircularRRectOp>(); 776c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 777c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth that->bounds(), caps)) { 778c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return false; 779c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 780c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 781c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) { 782c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return false; 783c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 784c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 785c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); 786c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth this->joinBounds(*that); 787c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fVertCount += that->fVertCount; 788c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth fIndexCount += that->fIndexCount; 789c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return true; 790c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 791c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 792c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth struct Geometry { 793fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon GrColor fColor; 794c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fOuterRadius; 795c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fInnerRadius; 796c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar fBlurRadius; 797c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkRect fDevBounds; 798c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth RRectType fType; 799c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth }; 800c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 801c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkSTArray<1, Geometry, true> fGeoData; 802fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkMatrix fViewMatrixIfUsingLocalCoords; 803fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon int fVertCount; 804fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon int fIndexCount; 805c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 806dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon typedef GrMeshDrawOp INHERITED; 807c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth}; 808c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 809c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth/////////////////////////////////////////////////////////////////////////////// 810c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 811649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomonstd::unique_ptr<GrMeshDrawOp> make_shadow_circle_op(GrColor color, 812649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkMatrix& viewMatrix, 813649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRect& oval, 814649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkScalar blurRadius, 815649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkStrokeRec& stroke, 816649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const GrShaderCaps* shaderCaps) { 817c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // we can only draw circles 818c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar width = oval.width(); 819c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(SkScalarNearlyEqual(width, oval.height()) && viewMatrix.isSimilarity()); 820fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkPoint center = {oval.centerX(), oval.centerY()}; 821fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon return ShadowCircleOp::Make(color, viewMatrix, center, width / 2.f, blurRadius, 822fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon GrStyle(stroke, nullptr)); 823c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 824c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 825649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomonstatic std::unique_ptr<GrMeshDrawOp> make_shadow_rrect_op(GrColor color, 826649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkMatrix& viewMatrix, 827649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRRect& rrect, 828649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkScalar blurRadius, 829649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkStrokeRec& stroke) { 830c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(viewMatrix.rectStaysRect()); 831c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(rrect.isSimple()); 832c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(!rrect.isOval()); 833c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 83453e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon // Shadow rrect ops only handle simple circular rrects. 83553e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon // Do any matrix crunching before we reset the draw state for device coords. 836c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const SkRect& rrectBounds = rrect.getBounds(); 837c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkRect bounds; 838c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth viewMatrix.mapRect(&bounds, rrectBounds); 839c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 840c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkVector radii = rrect.getSimpleRadii(); 841c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX] * radii.fX + 842c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth viewMatrix[SkMatrix::kMSkewY] * radii.fY); 843c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX] * radii.fX + 844c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth viewMatrix[SkMatrix::kMScaleY] * radii.fY); 845c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkASSERT(SkScalarNearlyEqual(xRadius, yRadius)); 846c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 847c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkStrokeRec::Style style = stroke.getStyle(); 848c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 849c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // Do (potentially) anisotropic mapping of stroke. Use -1s to indicate fill-only draws. 850fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkVector scaledStroke = {-1, -1}; 851c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar strokeWidth = stroke.getWidth(); 852c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 853fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon bool isStrokeOnly = 854fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style; 855c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; 856c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 857c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (hasStroke) { 858c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (SkStrokeRec::kHairline_Style == style) { 859c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth scaledStroke.set(1, 1); 860c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } else { 861fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon scaledStroke.fX = SkScalarAbs( 862fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon strokeWidth * (viewMatrix[SkMatrix::kMScaleX] + viewMatrix[SkMatrix::kMSkewY])); 863fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon scaledStroke.fY = SkScalarAbs( 864fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon strokeWidth * (viewMatrix[SkMatrix::kMSkewX] + viewMatrix[SkMatrix::kMScaleY])); 865c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 866c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 867c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // we don't handle anisotropic strokes 868c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!SkScalarNearlyEqual(scaledStroke.fX, scaledStroke.fY)) { 869c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return nullptr; 870c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 871c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 872c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 873c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // The way the effect interpolates the offset-to-ellipse/circle-center attribute only works on 874c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner rect of the nine- 875c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // patch will have fractional coverage. This only matters when the interior is actually filled. 876c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // We could consider falling back to rect rendering here, since a tiny radius is 877c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth // indistinguishable from a square corner. 878c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { 879c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return nullptr; 880c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 881c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 882649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon return std::unique_ptr<GrMeshDrawOp>(new ShadowCircularRRectOp( 883f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon color, viewMatrix, bounds, xRadius, blurRadius, scaledStroke.fX, isStrokeOnly)); 884c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 885c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 886fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomonnamespace GrShadowRRectOp { 887649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomonstd::unique_ptr<GrMeshDrawOp> Make(GrColor color, 888649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkMatrix& viewMatrix, 889649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRRect& rrect, 890649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkScalar blurRadius, 891649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkStrokeRec& stroke, 892649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const GrShaderCaps* shaderCaps) { 893c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (rrect.isOval()) { 89453e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon return make_shadow_circle_op(color, viewMatrix, rrect.getBounds(), blurRadius, stroke, 89553e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon shaderCaps); 896c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 897c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 898c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { 899c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth return nullptr; 900c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 901c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 90253e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon return make_shadow_rrect_op(color, viewMatrix, rrect, blurRadius, stroke); 903fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon} 904c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 905c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth/////////////////////////////////////////////////////////////////////////////// 906c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 9076f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 908c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 9095ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian SalomonDRAW_OP_TEST_DEFINE(ShadowCircleOp) { 910c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth do { 911c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar rotate = random->nextSScalar1() * 360.f; 912c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar translateX = random->nextSScalar1() * 1000.f; 913c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar translateY = random->nextSScalar1() * 1000.f; 914c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar scale = random->nextSScalar1() * 100.f; 915c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkMatrix viewMatrix; 916c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth viewMatrix.setRotate(rotate); 917c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth viewMatrix.postTranslate(translateX, translateY); 918c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth viewMatrix.postScale(scale, scale); 919c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth GrColor color = GrRandomColor(random); 920c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkRect circle = GrTest::TestSquare(random); 921fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkPoint center = {circle.centerX(), circle.centerY()}; 922c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar radius = circle.width() / 2.f; 923c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkStrokeRec stroke = GrTest::TestStrokeRec(random); 924c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar blurRadius = random->nextSScalar1() * 72.f; 925649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon std::unique_ptr<GrMeshDrawOp> op = ShadowCircleOp::Make( 926649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon color, viewMatrix, center, radius, blurRadius, GrStyle(stroke, nullptr)); 927fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon if (op) { 9285ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon return op; 929c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } 930c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth } while (true); 931c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 932c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 9335ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian SalomonDRAW_OP_TEST_DEFINE(ShadowRRectOp) { 934c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); 935c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth GrColor color = GrRandomColor(random); 936c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth const SkRRect& rrect = GrTest::TestRRectSimple(random); 937c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar blurRadius = random->nextSScalar1() * 72.f; 93853e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon return make_shadow_rrect_op(color, viewMatrix, rrect, blurRadius, 93953e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon GrTest::TestStrokeRec(random)); 940c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth} 941c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth 942c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth#endif 943