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; } }
// Will the given round rect look good if we use HW derivatives? static bool can_use_hw_derivatives_with_coverage( const GrShaderCaps& shaderCaps, const SkMatrix& viewMatrix, const SkRRect& rrect) { if (!shaderCaps.shaderDerivativeSupport()) { return false; } Sk2f x = Sk2f(viewMatrix.getScaleX(), viewMatrix.getSkewX()); Sk2f y = Sk2f(viewMatrix.getSkewY(), viewMatrix.getScaleY()); Sk2f devScale = (x*x + y*y).sqrt(); switch (rrect.getType()) { case SkRRect::kEmpty_Type: case SkRRect::kRect_Type: return true; case SkRRect::kOval_Type: case SkRRect::kSimple_Type: return can_use_hw_derivatives_with_coverage(devScale, rrect.getSimpleRadii()); case SkRRect::kNinePatch_Type: { Sk2f r0 = Sk2f::Load(SkRRectPriv::GetRadiiArray(rrect)); Sk2f r1 = Sk2f::Load(SkRRectPriv::GetRadiiArray(rrect) + 2); Sk2f minRadii = Sk2f::Min(r0, r1); Sk2f maxRadii = Sk2f::Max(r0, r1); return can_use_hw_derivatives_with_coverage(devScale, Sk2f(minRadii[0], maxRadii[1])) && can_use_hw_derivatives_with_coverage(devScale, Sk2f(maxRadii[0], minRadii[1])); } case SkRRect::kComplex_Type: { for (int i = 0; i < 4; ++i) { auto corner = static_cast<SkRRect::Corner>(i); if (!can_use_hw_derivatives_with_coverage(devScale, rrect.radii(corner))) { return false; } } return true; } } SK_ABORT("Invalid round rect type."); return false; // Add this return to keep GCC happy. }
static void toString(const SkRRect& rrect, SkString* str) { SkRect r = rrect.getBounds(); str->appendf("[%g,%g %g:%g]", SkScalarToFloat(r.fLeft), SkScalarToFloat(r.fTop), SkScalarToFloat(r.width()), SkScalarToFloat(r.height())); if (rrect.isOval()) { str->append("()"); } else if (rrect.isSimple()) { const SkVector& rad = rrect.getSimpleRadii(); str->appendf("(%g,%g)", rad.x(), rad.y()); } else if (rrect.isComplex()) { SkVector radii[4] = { rrect.radii(SkRRect::kUpperLeft_Corner), rrect.radii(SkRRect::kUpperRight_Corner), rrect.radii(SkRRect::kLowerRight_Corner), rrect.radii(SkRRect::kLowerLeft_Corner), }; str->appendf("(%g,%g %g,%g %g,%g %g,%g)", radii[0].x(), radii[0].y(), radii[1].x(), radii[1].y(), radii[2].x(), radii[2].y(), radii[3].x(), radii[3].y()); } }