void GrAARectRenderer::fillAARect(GrGpu* gpu, GrDrawTarget* target, const GrRect& devRect, bool useVertexCoverage) { GrVertexLayout layout = aa_rect_layout(useVertexCoverage); size_t vsize = GrDrawState::VertexSize(layout); GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu); if (NULL == indexBuffer) { GrPrintf("Failed to create index buffer!\n"); return; } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts); GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize); set_inset_fan(fan0Pos, vsize, devRect, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan1Pos, vsize, devRect, SK_ScalarHalf, SK_ScalarHalf); verts += sizeof(GrPoint); for (int i = 0; i < 4; ++i) { *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; } GrColor innerColor; if (useVertexCoverage) { innerColor = 0xffffffff; } else { innerColor = target->getDrawState().getColor(); } verts += 4 * vsize; for (int i = 0; i < 4; ++i) { *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor; } target->setIndexSourceToBuffer(indexBuffer); target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, kVertsPerAAFillRect, kIndicesPerAAFillRect); }
void GrAARectRenderer::strokeAARect(GrGpu* gpu, GrDrawTarget* target, const GrRect& devRect, const GrVec& devStrokeSize, bool useVertexCoverage) { const SkScalar& dx = devStrokeSize.fX; const SkScalar& dy = devStrokeSize.fY; const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf); const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf); SkScalar spare; { SkScalar w = devRect.width() - dx; SkScalar h = devRect.height() - dy; spare = GrMin(w, h); } if (spare <= 0) { GrRect r(devRect); r.inset(-rx, -ry); this->fillAARect(gpu, target, r, useVertexCoverage); return; } GrVertexLayout layout = aa_rect_layout(useVertexCoverage); size_t vsize = GrDrawTarget::VertexSize(layout); GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu); if (NULL == indexBuffer) { GrPrintf("Failed to create index buffer!\n"); return; } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); // We create vertices for four nested rectangles. There are two ramps from 0 to full // coverage, one on the exterior of the stroke and the other on the interior. // The following pointers refer to the four rects, from outermost to innermost. GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts); GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize); GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize); GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize); set_inset_fan(fan0Pos, vsize, devRect, -rx - SK_ScalarHalf, -ry - SK_ScalarHalf); set_inset_fan(fan1Pos, vsize, devRect, -rx + SK_ScalarHalf, -ry + SK_ScalarHalf); set_inset_fan(fan2Pos, vsize, devRect, rx - SK_ScalarHalf, ry - SK_ScalarHalf); set_inset_fan(fan3Pos, vsize, devRect, rx + SK_ScalarHalf, ry + SK_ScalarHalf); // The outermost rect has 0 coverage verts += sizeof(GrPoint); for (int i = 0; i < 4; ++i) { *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; } // The inner two rects have full coverage GrColor innerColor; if (useVertexCoverage) { innerColor = 0xffffffff; } else { innerColor = target->getDrawState().getColor(); } verts += 4 * vsize; for (int i = 0; i < 8; ++i) { *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor; } // The innermost rect has full coverage verts += 8 * vsize; for (int i = 0; i < 4; ++i) { *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; } target->setIndexSourceToBuffer(indexBuffer); target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, aaStrokeRectIndexCount()); }
void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target, GrDrawState* drawState, GrColor color, const SkRect& devOutside, const SkRect& devOutsideAssist, const SkRect& devInside, bool miterStroke) { GrDrawState::AutoRestoreEffects are(drawState); CoverageAttribType type; SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(*drawState, color, &type)); int innerVertexNum = 4; int outerVertexNum = miterStroke ? 4 : 8; int totalVertexNum = (outerVertexNum + innerVertexNum) * 2; size_t vstride = gp->getVertexStride(); GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, vstride, 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return; } GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(miterStroke); if (NULL == indexBuffer) { SkDebugf("Failed to create index buffer!\n"); return; } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); // We create vertices for four nested rectangles. There are two ramps from 0 to full // coverage, one on the exterior of the stroke and the other on the interior. // The following pointers refer to the four rects, from outermost to innermost. SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vstride); SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vstride); SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vstride); #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX // TODO: this only really works if the X & Y margins are the same all around // the rect (or if they are all >= 1.0). SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight); inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft); inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop); if (miterStroke) { inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom); } else { inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - devInside.fBottom); } SkASSERT(inset >= 0); #else SkScalar inset = SK_ScalarHalf; #endif if (miterStroke) { // outermost set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); // inner two set_inset_fan(fan1Pos, vstride, devOutside, inset, inset); set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset); // innermost set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHalf); } else { SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vstride); SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertexNum + 4) * vstride); // outermost set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan0AssistPos, vstride, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf); // outer one of the inner two set_inset_fan(fan1Pos, vstride, devOutside, inset, inset); set_inset_fan(fan1AssistPos, vstride, devOutsideAssist, inset, inset); // inner one of the inner two set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset); // innermost set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHalf); } // Make verts point to vertex color and then set all the color and coverage vertex attrs values. // The outermost rect has 0 coverage verts += sizeof(SkPoint); for (int i = 0; i < outerVertexNum; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vstride) = color; *reinterpret_cast<float*>(verts + i * vstride + sizeof(GrColor)) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; } } // scale is the coverage for the the inner two rects. int scale; if (inset < SK_ScalarHalf) { scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); SkASSERT(scale >= 0 && scale <= 255); } else { scale = 0xff; } float innerCoverage = GrNormalizeByteToFloat(scale); GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); verts += outerVertexNum * vstride; for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vstride) = color; *reinterpret_cast<float*>(verts + i * vstride + sizeof(GrColor)) = innerCoverage; } else { *reinterpret_cast<GrColor*>(verts + i * vstride) = scaledColor; } } // The innermost rect has 0 coverage verts += (outerVertexNum + innerVertexNum) * vstride; for (int i = 0; i < innerVertexNum; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vstride) = color; *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; } } target->setIndexSourceToBuffer(indexBuffer); target->drawIndexedInstances(drawState, gp, kTriangles_GrPrimitiveType, 1, totalVertexNum, aa_stroke_rect_index_count(miterStroke)); target->resetIndexSource(); }
void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target, GrDrawState* drawState, GrColor color, const SkRect& rect, const SkMatrix& combinedMatrix, const SkRect& devRect) { GrDrawState::AutoRestoreEffects are(drawState); CoverageAttribType type; SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(*drawState, color, &type)); size_t vertexStride = gp->getVertexStride(); GrDrawTarget::AutoReleaseGeometry geo(target, 8, vertexStride, 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return; } if (NULL == fAAFillRectIndexBuffer) { fAAFillRectIndexBuffer = fGpu->createInstancedIndexBuffer(gFillAARectIdx, kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect); } GrIndexBuffer* indexBuffer = fAAFillRectIndexBuffer; if (NULL == indexBuffer) { SkDebugf("Failed to create index buffer!\n"); return; } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1); inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); if (combinedMatrix.rectStaysRect()) { // Temporarily #if'ed out. We don't want to pass in the devRect but // right now it is computed in GrContext::apply_aa_to_rect and we don't // want to throw away the work #if 0 SkRect devRect; combinedMatrix.mapRect(&devRect, rect); #endif set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset); } else { // compute transformed (1, 0) and (0, 1) vectors SkVector vec[2] = { { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } }; vec[0].normalize(); vec[0].scale(SK_ScalarHalf); vec[1].normalize(); vec[1].scale(SK_ScalarHalf); // create the rotated rect fan0Pos->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride); combinedMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); // Now create the inset points and then outset the original // rotated points // TL *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1]; // BL *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1]; // BR *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1]; // TR *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1]; } // Make verts point to vertex color and then set all the color and coverage vertex attrs values. verts += sizeof(SkPoint); for (int i = 0; i < 4; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; } } int scale; if (inset < SK_ScalarHalf) { scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); SkASSERT(scale >= 0 && scale <= 255); } else { scale = 0xff; } verts += 4 * vertexStride; float innerCoverage = GrNormalizeByteToFloat(scale); GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); for (int i = 0; i < 4; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = innerCoverage; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; } } target->setIndexSourceToBuffer(indexBuffer); target->drawIndexedInstances(drawState, gp, kTriangles_GrPrimitiveType, 1, kVertsPerAAFillRect, kIndicesPerAAFillRect); target->resetIndexSource(); }
static void generate_aa_fill_rect_geometry(intptr_t verts, size_t vertexStride, GrColor color, const SkMatrix& viewMatrix, const SkRect& rect, const SkRect& devRect, bool tweakAlphaForCoverage, const SkMatrix* localMatrix) { SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); SkScalar inset; if (viewMatrix.rectStaysRect()) { inset = SkMinScalar(devRect.width(), SK_Scalar1); inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset); } else { // compute transformed (1, 0) and (0, 1) vectors SkVector vec[2] = {{viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY]}, {viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY]}}; SkScalar len1 = SkPoint::Normalize(&vec[0]); vec[0].scale(SK_ScalarHalf); SkScalar len2 = SkPoint::Normalize(&vec[1]); vec[1].scale(SK_ScalarHalf); inset = SkMinScalar(len1 * rect.width(), SK_Scalar1); inset = SK_ScalarHalf * SkMinScalar(inset, len2 * rect.height()); // create the rotated rect SkPointPriv::SetRectFan(fan0Pos, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride); SkMatrixPriv::MapPointsWithStride(viewMatrix, fan0Pos, vertexStride, 4); // Now create the inset points and then outset the original // rotated points // TL *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1]; // BL *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1]; // BR *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1]; // TR *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1]; } if (localMatrix) { SkMatrix invViewMatrix; if (!viewMatrix.invert(&invViewMatrix)) { SkDebugf("View matrix is non-invertible, local coords will be wrong."); invViewMatrix = SkMatrix::I(); } SkMatrix localCoordMatrix; localCoordMatrix.setConcat(*localMatrix, invViewMatrix); SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(verts + sizeof(SkPoint) + sizeof(GrColor)); SkMatrixPriv::MapPointsWithStride(localCoordMatrix, fan0Loc, vertexStride, fan0Pos, vertexStride, 8); } // Make verts point to vertex color and then set all the color and coverage vertex attrs // values. verts += sizeof(SkPoint); // The coverage offset is always the last vertex attribute intptr_t coverageOffset = vertexStride - sizeof(GrColor) - sizeof(SkPoint); for (int i = 0; i < 4; ++i) { if (tweakAlphaForCoverage) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = 0; } } int scale; if (inset < SK_ScalarHalf) { scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); SkASSERT(scale >= 0 && scale <= 255); } else { scale = 0xff; } verts += 4 * vertexStride; float innerCoverage = GrNormalizeByteToFloat(scale); GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); for (int i = 0; i < 4; ++i) { if (tweakAlphaForCoverage) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = innerCoverage; } } }
void generateAAStrokeRectGeometry(void* vertices, size_t offset, size_t vertexStride, int outerVertexNum, int innerVertexNum, GrColor color, const SkRect& devOutside, const SkRect& devOutsideAssist, const SkRect& devInside, bool miterStroke, bool tweakAlphaForCoverage) const { intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; // We create vertices for four nested rectangles. There are two ramps from 0 to full // coverage, one on the exterior of the stroke and the other on the interior. // The following pointers refer to the four rects, from outermost to innermost. SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vertexStride); SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vertexStride); SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vertexStride); #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX // TODO: this only really works if the X & Y margins are the same all around // the rect (or if they are all >= 1.0). SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight); inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft); inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop); if (miterStroke) { inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom); } else { inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - devInside.fBottom); } SkASSERT(inset >= 0); #else SkScalar inset = SK_ScalarHalf; #endif if (miterStroke) { // outermost set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); // inner two set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset); set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset); // innermost set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK_ScalarHalf); } else { SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertexNum + 4) * vertexStride); // outermost set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan0AssistPos, vertexStride, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf); // outer one of the inner two set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset); set_inset_fan(fan1AssistPos, vertexStride, devOutsideAssist, inset, inset); // inner one of the inner two set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset); // innermost set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK_ScalarHalf); } // Make verts point to vertex color and then set all the color and coverage vertex attrs // values. The outermost rect has 0 coverage verts += sizeof(SkPoint); for (int i = 0; i < outerVertexNum; ++i) { if (tweakAlphaForCoverage) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 0; } } // scale is the coverage for the the inner two rects. int scale; if (inset < SK_ScalarHalf) { scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); SkASSERT(scale >= 0 && scale <= 255); } else { scale = 0xff; } float innerCoverage = GrNormalizeByteToFloat(scale); GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); verts += outerVertexNum * vertexStride; for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { if (tweakAlphaForCoverage) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = innerCoverage; } } // The innermost rect has 0 coverage verts += (outerVertexNum + innerVertexNum) * vertexStride; for (int i = 0; i < innerVertexNum; ++i) { if (tweakAlphaForCoverage) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(GrColor)) = 0; } } }
void generateAAFillRectGeometry(void* vertices, size_t offset, size_t vertexStride, GrColor color, const SkMatrix& viewMatrix, const SkRect& rect, const SkRect& devRect, bool tweakAlphaForCoverage) const { intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1); inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); if (viewMatrix.rectStaysRect()) { set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset); } else { // compute transformed (1, 0) and (0, 1) vectors SkVector vec[2] = { { viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY] }, { viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY] } }; vec[0].normalize(); vec[0].scale(SK_ScalarHalf); vec[1].normalize(); vec[1].scale(SK_ScalarHalf); // create the rotated rect fan0Pos->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride); viewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); // Now create the inset points and then outset the original // rotated points // TL *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1]; // BL *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1]; // BR *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1]; // TR *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1]; } // Make verts point to vertex color and then set all the color and coverage vertex attrs // values. verts += sizeof(SkPoint); for (int i = 0; i < 4; ++i) { if (tweakAlphaForCoverage) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 0; } } int scale; if (inset < SK_ScalarHalf) { scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); SkASSERT(scale >= 0 && scale <= 255); } else { scale = 0xff; } verts += 4 * vertexStride; float innerCoverage = GrNormalizeByteToFloat(scale); GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); for (int i = 0; i < 4; ++i) { if (tweakAlphaForCoverage) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = innerCoverage; } } }