GrFillRRectOp::GrFillRRectOp( GrAAType aaType, const SkRRect& rrect, Flags flags, const SkMatrix& totalShapeMatrix, GrPaint&& paint, const SkRect& devBounds) : GrDrawOp(ClassID()) , fAAType(aaType) , fOriginalColor(paint.getColor4f()) , fLocalRect(rrect.rect()) , fFlags(flags) , fProcessors(std::move(paint)) { SkASSERT((fFlags & Flags::kHasPerspective) == totalShapeMatrix.hasPerspective()); this->setBounds(devBounds, GrOp::HasAABloat::kYes, GrOp::IsZeroArea::kNo); // Write the matrix attribs. const SkMatrix& m = totalShapeMatrix; if (!(fFlags & Flags::kHasPerspective)) { // Affine 2D transformation (float2x2 plus float2 translate). SkASSERT(!m.hasPerspective()); this->writeInstanceData(m.getScaleX(), m.getSkewX(), m.getSkewY(), m.getScaleY()); this->writeInstanceData(m.getTranslateX(), m.getTranslateY()); } else { // Perspective float3x3 transformation matrix. SkASSERT(m.hasPerspective()); m.get9(this->appendInstanceData<float>(9)); } // Convert the radii to [-1, -1, +1, +1] space and write their attribs. Sk4f radiiX, radiiY; Sk4f::Load2(SkRRectPriv::GetRadiiArray(rrect), &radiiX, &radiiY); (radiiX * (2/rrect.width())).store(this->appendInstanceData<float>(4)); (radiiY * (2/rrect.height())).store(this->appendInstanceData<float>(4)); // We will write the color and local rect attribs during finalize(). }
void InstancedRendering::Batch::appendRRectParams(const SkRRect& rrect) { SkASSERT(!fIsTracked); switch (rrect.getType()) { case SkRRect::kSimple_Type: { const SkVector& radii = rrect.getSimpleRadii(); this->appendParamsTexel(radii.x(), radii.y(), rrect.width(), rrect.height()); return; } case SkRRect::kNinePatch_Type: { float twoOverW = 2 / rrect.width(); float twoOverH = 2 / rrect.height(); const SkVector& radiiTL = rrect.radii(SkRRect::kUpperLeft_Corner); const SkVector& radiiBR = rrect.radii(SkRRect::kLowerRight_Corner); this->appendParamsTexel(radiiTL.x() * twoOverW, radiiBR.x() * twoOverW, radiiTL.y() * twoOverH, radiiBR.y() * twoOverH); return; } case SkRRect::kComplex_Type: { /** * The x and y radii of each arc are stored in separate vectors, * in the following order: * * __x1 _ _ _ x3__ * y1 | | y2 * * | | * * y3 |__ _ _ _ __| y4 * x2 x4 * */ float twoOverW = 2 / rrect.width(); float twoOverH = 2 / rrect.height(); const SkVector& radiiTL = rrect.radii(SkRRect::kUpperLeft_Corner); const SkVector& radiiTR = rrect.radii(SkRRect::kUpperRight_Corner); const SkVector& radiiBR = rrect.radii(SkRRect::kLowerRight_Corner); const SkVector& radiiBL = rrect.radii(SkRRect::kLowerLeft_Corner); this->appendParamsTexel(radiiTL.x() * twoOverW, radiiBL.x() * twoOverW, radiiTR.x() * twoOverW, radiiBR.x() * twoOverW); this->appendParamsTexel(radiiTL.y() * twoOverH, radiiTR.y() * twoOverH, radiiBL.y() * twoOverH, radiiBR.y() * twoOverH); return; } default: return; } }
void initialize(const SkRRect& rrect, const SkPoint& p, const SkVector& s) { objectNode = sksg::RRect::Make(rrect); shadowNode = sksg::RRect::Make(rrect); pos = p; spd = s; size = SkSize::Make(rrect.width(), rrect.height()); }
void initialize(const SkRRect& rrect, SkColor color, const SkPoint& p, const SkVector& s) { objectNode = make_svg_rrect(rrect); objectNode->setFill(SkSVGPaint(SkSVGColorType(color))); shadowNode = make_svg_rrect(rrect); shadowNode->setFillOpacity(SkSVGNumberType(kShadowOpacity)); pos = p; spd = s; size = SkSize::Make(rrect.width(), rrect.height()); }
// Test out the case where an oval already off in space is translated/scaled // further off into space - yielding numerical issues when the rect & radii // are transformed separatly // BUG=skia:2696 static void test_issue_2696(skiatest::Reporter* reporter) { SkRRect rrect; SkRect r = { 28443.8594f, 53.1428604f, 28446.7148f, 56.0000038f }; rrect.setOval(r); SkMatrix xform; xform.setAll(2.44f, 0.0f, 485411.7f, 0.0f, 2.44f, -438.7f, 0.0f, 0.0f, 1.0f); SkRRect dst; bool success = rrect.transform(xform, &dst); REPORTER_ASSERT(reporter, success); SkScalar halfWidth = SkScalarHalf(dst.width()); SkScalar halfHeight = SkScalarHalf(dst.height()); for (int i = 0; i < 4; ++i) { REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.radii((SkRRect::Corner)i).fX, halfWidth)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.radii((SkRRect::Corner)i).fY, halfHeight)); } }