Better encapsulate oval/rrect batchs.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2104423003 Committed: https://skia.googlesource.com/skia/+/5fd209e8ee477c703bc5c11b008f247d515fc0fc Review-Url: https://codereview.chromium.org/2104423003
This commit is contained in:
parent
fc5b70a8e4
commit
7f06c6947a
@ -524,49 +524,58 @@ sk_sp<GrGeometryProcessor> DIEllipseGeometryProcessor::TestCreate(GrProcessorTes
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrDrawBatch* GrOvalRenderer::CreateOvalBatch(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& oval,
|
||||
const SkStrokeRec& stroke,
|
||||
GrShaderCaps* shaderCaps) {
|
||||
// we can draw circles
|
||||
if (SkScalarNearlyEqual(oval.width(), oval.height()) && circle_stays_circle(viewMatrix)) {
|
||||
return CreateCircleBatch(color, viewMatrix, oval, stroke);
|
||||
}
|
||||
|
||||
// if we have shader derivative support, render as device-independent
|
||||
if (shaderCaps->shaderDerivativeSupport()) {
|
||||
return CreateDIEllipseBatch(color, viewMatrix, oval, stroke);
|
||||
}
|
||||
|
||||
// otherwise axis-aligned ellipses only
|
||||
if (viewMatrix.rectStaysRect()) {
|
||||
return CreateEllipseBatch(color, viewMatrix, oval, stroke);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CircleBatch : public GrVertexBatch {
|
||||
public:
|
||||
DEFINE_BATCH_CLASS_ID
|
||||
|
||||
struct Geometry {
|
||||
SkRect fDevBounds;
|
||||
SkScalar fInnerRadius;
|
||||
SkScalar fOuterRadius;
|
||||
GrColor fColor;
|
||||
};
|
||||
CircleBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& circle,
|
||||
const SkStrokeRec& stroke)
|
||||
: INHERITED(ClassID())
|
||||
, fViewMatrixIfUsingLocalCoords(viewMatrix) {
|
||||
SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY());
|
||||
viewMatrix.mapPoints(¢er, 1);
|
||||
SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width()));
|
||||
SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth());
|
||||
|
||||
CircleBatch(const Geometry& geometry, const SkMatrix& viewMatrix, bool stroked)
|
||||
: INHERITED(ClassID())
|
||||
, fStroked(stroked)
|
||||
, fViewMatrixIfUsingLocalCoords(viewMatrix) {
|
||||
fGeoData.push_back(geometry);
|
||||
this->setBounds(geometry.fDevBounds);
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
|
||||
SkStrokeRec::kHairline_Style == style;
|
||||
bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
|
||||
|
||||
SkScalar innerRadius = 0.0f;
|
||||
SkScalar outerRadius = radius;
|
||||
SkScalar halfWidth = 0;
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(strokeWidth)) {
|
||||
halfWidth = SK_ScalarHalf;
|
||||
} else {
|
||||
halfWidth = SkScalarHalf(strokeWidth);
|
||||
}
|
||||
|
||||
outerRadius += halfWidth;
|
||||
if (isStrokeOnly) {
|
||||
innerRadius = radius - halfWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// The radii are outset for two reasons. First, it allows the shader to simply perform
|
||||
// simpler computation because the computed alpha is zero, rather than 50%, at the radius.
|
||||
// Second, the outer radius is used to compute the verts of the bounding box that is
|
||||
// rendered and the outset ensures the box will cover all partially covered by the circle.
|
||||
outerRadius += SK_ScalarHalf;
|
||||
innerRadius -= SK_ScalarHalf;
|
||||
|
||||
fGeoData.emplace_back(Geometry {
|
||||
color,
|
||||
innerRadius,
|
||||
outerRadius,
|
||||
SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius,
|
||||
center.fX + outerRadius, center.fY + outerRadius)
|
||||
});
|
||||
this->setBounds(fGeoData.back().fDevBounds);
|
||||
fStroked = isStrokeOnly && innerRadius > 0;
|
||||
}
|
||||
|
||||
const char* name() const override { return "CircleBatch"; }
|
||||
|
||||
SkString dumpInfo() const override {
|
||||
@ -680,6 +689,13 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Geometry {
|
||||
GrColor fColor;
|
||||
SkScalar fInnerRadius;
|
||||
SkScalar fOuterRadius;
|
||||
SkRect fDevBounds;
|
||||
};
|
||||
|
||||
bool fStroked;
|
||||
SkMatrix fViewMatrixIfUsingLocalCoords;
|
||||
SkSTArray<1, Geometry, true> fGeoData;
|
||||
@ -687,81 +703,89 @@ private:
|
||||
typedef GrVertexBatch INHERITED;
|
||||
};
|
||||
|
||||
static GrDrawBatch* create_circle_batch(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& circle,
|
||||
const SkStrokeRec& stroke) {
|
||||
SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY());
|
||||
viewMatrix.mapPoints(¢er, 1);
|
||||
SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width()));
|
||||
SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth());
|
||||
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
|
||||
SkStrokeRec::kHairline_Style == style;
|
||||
bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
|
||||
|
||||
SkScalar innerRadius = 0.0f;
|
||||
SkScalar outerRadius = radius;
|
||||
SkScalar halfWidth = 0;
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(strokeWidth)) {
|
||||
halfWidth = SK_ScalarHalf;
|
||||
} else {
|
||||
halfWidth = SkScalarHalf(strokeWidth);
|
||||
}
|
||||
|
||||
outerRadius += halfWidth;
|
||||
if (isStrokeOnly) {
|
||||
innerRadius = radius - halfWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// The radii are outset for two reasons. First, it allows the shader to simply perform simpler
|
||||
// computation because the computed alpha is zero, rather than 50%, at the radius.
|
||||
// Second, the outer radius is used to compute the verts of the bounding box that is rendered
|
||||
// and the outset ensures the box will cover all partially covered by the circle.
|
||||
outerRadius += SK_ScalarHalf;
|
||||
innerRadius -= SK_ScalarHalf;
|
||||
|
||||
CircleBatch::Geometry geometry;
|
||||
geometry.fColor = color;
|
||||
geometry.fInnerRadius = innerRadius;
|
||||
geometry.fOuterRadius = outerRadius;
|
||||
geometry.fDevBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius,
|
||||
center.fX + outerRadius, center.fY + outerRadius);
|
||||
|
||||
return new CircleBatch(geometry, viewMatrix, isStrokeOnly && innerRadius > 0);
|
||||
}
|
||||
|
||||
GrDrawBatch* GrOvalRenderer::CreateCircleBatch(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& circle,
|
||||
const SkStrokeRec& stroke) {
|
||||
return create_circle_batch(color, viewMatrix, circle, stroke);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EllipseBatch : public GrVertexBatch {
|
||||
public:
|
||||
DEFINE_BATCH_CLASS_ID
|
||||
static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& ellipse,
|
||||
const SkStrokeRec& stroke) {
|
||||
SkASSERT(viewMatrix.rectStaysRect());
|
||||
|
||||
struct Geometry {
|
||||
SkRect fDevBounds;
|
||||
SkScalar fXRadius;
|
||||
SkScalar fYRadius;
|
||||
SkScalar fInnerXRadius;
|
||||
SkScalar fInnerYRadius;
|
||||
GrColor fColor;
|
||||
};
|
||||
// do any matrix crunching before we reset the draw state for device coords
|
||||
SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
|
||||
viewMatrix.mapPoints(¢er, 1);
|
||||
SkScalar ellipseXRadius = SkScalarHalf(ellipse.width());
|
||||
SkScalar ellipseYRadius = SkScalarHalf(ellipse.height());
|
||||
SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*ellipseXRadius +
|
||||
viewMatrix[SkMatrix::kMSkewY]*ellipseYRadius);
|
||||
SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*ellipseXRadius +
|
||||
viewMatrix[SkMatrix::kMScaleY]*ellipseYRadius);
|
||||
|
||||
EllipseBatch(const Geometry& geometry, const SkMatrix& viewMatrix, bool stroked)
|
||||
: INHERITED(ClassID())
|
||||
, fStroked(stroked)
|
||||
, fViewMatrixIfUsingLocalCoords(viewMatrix) {
|
||||
fGeoData.push_back(geometry);
|
||||
this->setBounds(geometry.fDevBounds);
|
||||
// do (potentially) anisotropic mapping of stroke
|
||||
SkVector scaledStroke;
|
||||
SkScalar strokeWidth = stroke.getWidth();
|
||||
scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMScaleX] +
|
||||
viewMatrix[SkMatrix::kMSkewY]));
|
||||
scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSkewX] +
|
||||
viewMatrix[SkMatrix::kMScaleY]));
|
||||
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
|
||||
SkStrokeRec::kHairline_Style == style;
|
||||
bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
|
||||
|
||||
SkScalar innerXRadius = 0;
|
||||
SkScalar innerYRadius = 0;
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(scaledStroke.length())) {
|
||||
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
|
||||
} else {
|
||||
scaledStroke.scale(SK_ScalarHalf);
|
||||
}
|
||||
|
||||
// we only handle thick strokes for near-circular ellipses
|
||||
if (scaledStroke.length() > SK_ScalarHalf &&
|
||||
(SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we don't handle it if curvature of the stroke is less than curvature of the ellipse
|
||||
if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius ||
|
||||
scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// this is legit only if scale & translation (which should be the case at the moment)
|
||||
if (isStrokeOnly) {
|
||||
innerXRadius = xRadius - scaledStroke.fX;
|
||||
innerYRadius = yRadius - scaledStroke.fY;
|
||||
}
|
||||
|
||||
xRadius += scaledStroke.fX;
|
||||
yRadius += scaledStroke.fY;
|
||||
}
|
||||
|
||||
// We've extended the outer x radius out half a pixel to antialias.
|
||||
// This will also expand the rect so all the pixels will be captured.
|
||||
// TODO: Consider if we should use sqrt(2)/2 instead
|
||||
xRadius += SK_ScalarHalf;
|
||||
yRadius += SK_ScalarHalf;
|
||||
|
||||
EllipseBatch* batch = new EllipseBatch();
|
||||
batch->fGeoData.emplace_back(Geometry {
|
||||
color,
|
||||
xRadius,
|
||||
yRadius,
|
||||
innerXRadius,
|
||||
innerYRadius,
|
||||
SkRect::MakeLTRB(center.fX - xRadius, center.fY - yRadius,
|
||||
center.fX + xRadius, center.fY + yRadius)
|
||||
});
|
||||
batch->fStroked = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0;
|
||||
batch->fViewMatrixIfUsingLocalCoords = viewMatrix;
|
||||
batch->setBounds(batch->fGeoData.back().fDevBounds);
|
||||
return batch;
|
||||
}
|
||||
|
||||
const char* name() const override { return "EllipseBatch"; }
|
||||
@ -775,6 +799,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
EllipseBatch() : INHERITED(ClassID()) {}
|
||||
|
||||
void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
|
||||
// Handle any overrides that affect our GP.
|
||||
if (!overrides.readsCoverage()) {
|
||||
@ -870,6 +896,14 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Geometry {
|
||||
GrColor fColor;
|
||||
SkScalar fXRadius;
|
||||
SkScalar fYRadius;
|
||||
SkScalar fInnerXRadius;
|
||||
SkScalar fInnerYRadius;
|
||||
SkRect fDevBounds;
|
||||
};
|
||||
|
||||
bool fStroked;
|
||||
SkMatrix fViewMatrixIfUsingLocalCoords;
|
||||
@ -878,113 +912,89 @@ private:
|
||||
typedef GrVertexBatch INHERITED;
|
||||
};
|
||||
|
||||
static GrDrawBatch* create_ellipse_batch(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& ellipse,
|
||||
const SkStrokeRec& stroke) {
|
||||
SkASSERT(viewMatrix.rectStaysRect());
|
||||
|
||||
// do any matrix crunching before we reset the draw state for device coords
|
||||
SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
|
||||
viewMatrix.mapPoints(¢er, 1);
|
||||
SkScalar ellipseXRadius = SkScalarHalf(ellipse.width());
|
||||
SkScalar ellipseYRadius = SkScalarHalf(ellipse.height());
|
||||
SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*ellipseXRadius +
|
||||
viewMatrix[SkMatrix::kMSkewY]*ellipseYRadius);
|
||||
SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*ellipseXRadius +
|
||||
viewMatrix[SkMatrix::kMScaleY]*ellipseYRadius);
|
||||
|
||||
// do (potentially) anisotropic mapping of stroke
|
||||
SkVector scaledStroke;
|
||||
SkScalar strokeWidth = stroke.getWidth();
|
||||
scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMScaleX] +
|
||||
viewMatrix[SkMatrix::kMSkewY]));
|
||||
scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSkewX] +
|
||||
viewMatrix[SkMatrix::kMScaleY]));
|
||||
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
|
||||
SkStrokeRec::kHairline_Style == style;
|
||||
bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
|
||||
|
||||
SkScalar innerXRadius = 0;
|
||||
SkScalar innerYRadius = 0;
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(scaledStroke.length())) {
|
||||
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
|
||||
} else {
|
||||
scaledStroke.scale(SK_ScalarHalf);
|
||||
}
|
||||
|
||||
// we only handle thick strokes for near-circular ellipses
|
||||
if (scaledStroke.length() > SK_ScalarHalf &&
|
||||
(SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we don't handle it if curvature of the stroke is less than curvature of the ellipse
|
||||
if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius ||
|
||||
scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// this is legit only if scale & translation (which should be the case at the moment)
|
||||
if (isStrokeOnly) {
|
||||
innerXRadius = xRadius - scaledStroke.fX;
|
||||
innerYRadius = yRadius - scaledStroke.fY;
|
||||
}
|
||||
|
||||
xRadius += scaledStroke.fX;
|
||||
yRadius += scaledStroke.fY;
|
||||
}
|
||||
|
||||
// We've extended the outer x radius out half a pixel to antialias.
|
||||
// This will also expand the rect so all the pixels will be captured.
|
||||
// TODO: Consider if we should use sqrt(2)/2 instead
|
||||
xRadius += SK_ScalarHalf;
|
||||
yRadius += SK_ScalarHalf;
|
||||
|
||||
EllipseBatch::Geometry geometry;
|
||||
geometry.fColor = color;
|
||||
geometry.fXRadius = xRadius;
|
||||
geometry.fYRadius = yRadius;
|
||||
geometry.fInnerXRadius = innerXRadius;
|
||||
geometry.fInnerYRadius = innerYRadius;
|
||||
geometry.fDevBounds = SkRect::MakeLTRB(center.fX - xRadius, center.fY - yRadius,
|
||||
center.fX + xRadius, center.fY + yRadius);
|
||||
|
||||
return new EllipseBatch(geometry, viewMatrix,
|
||||
isStrokeOnly && innerXRadius > 0 && innerYRadius > 0);
|
||||
}
|
||||
|
||||
GrDrawBatch* GrOvalRenderer::CreateEllipseBatch(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& ellipse,
|
||||
const SkStrokeRec& stroke) {
|
||||
return create_ellipse_batch(color, viewMatrix, ellipse, stroke);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DIEllipseBatch : public GrVertexBatch {
|
||||
public:
|
||||
DEFINE_BATCH_CLASS_ID
|
||||
|
||||
struct Geometry {
|
||||
SkMatrix fViewMatrix;
|
||||
SkRect fBounds;
|
||||
SkScalar fXRadius;
|
||||
SkScalar fYRadius;
|
||||
SkScalar fInnerXRadius;
|
||||
SkScalar fInnerYRadius;
|
||||
SkScalar fGeoDx;
|
||||
SkScalar fGeoDy;
|
||||
GrColor fColor;
|
||||
DIEllipseStyle fStyle;
|
||||
};
|
||||
static GrDrawBatch* Create(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& ellipse,
|
||||
const SkStrokeRec& stroke) {
|
||||
SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
|
||||
SkScalar xRadius = SkScalarHalf(ellipse.width());
|
||||
SkScalar yRadius = SkScalarHalf(ellipse.height());
|
||||
|
||||
static GrDrawBatch* Create(const Geometry& geometry, const SkRect& bounds) {
|
||||
return new DIEllipseBatch(geometry, bounds);
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
DIEllipseStyle dieStyle = (SkStrokeRec::kStroke_Style == style) ?
|
||||
DIEllipseStyle::kStroke :
|
||||
(SkStrokeRec::kHairline_Style == style) ?
|
||||
DIEllipseStyle::kHairline : DIEllipseStyle::kFill;
|
||||
|
||||
SkScalar innerXRadius = 0;
|
||||
SkScalar innerYRadius = 0;
|
||||
if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != style) {
|
||||
SkScalar strokeWidth = stroke.getWidth();
|
||||
|
||||
if (SkScalarNearlyZero(strokeWidth)) {
|
||||
strokeWidth = SK_ScalarHalf;
|
||||
} else {
|
||||
strokeWidth *= SK_ScalarHalf;
|
||||
}
|
||||
|
||||
// we only handle thick strokes for near-circular ellipses
|
||||
if (strokeWidth > SK_ScalarHalf &&
|
||||
(SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we don't handle it if curvature of the stroke is less than curvature of the ellipse
|
||||
if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius ||
|
||||
strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// set inner radius (if needed)
|
||||
if (SkStrokeRec::kStroke_Style == style) {
|
||||
innerXRadius = xRadius - strokeWidth;
|
||||
innerYRadius = yRadius - strokeWidth;
|
||||
}
|
||||
|
||||
xRadius += strokeWidth;
|
||||
yRadius += strokeWidth;
|
||||
}
|
||||
if (DIEllipseStyle::kStroke == dieStyle) {
|
||||
dieStyle = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseStyle ::kStroke :
|
||||
DIEllipseStyle ::kFill;
|
||||
}
|
||||
|
||||
// This expands the outer rect so that after CTM we end up with a half-pixel border
|
||||
SkScalar a = viewMatrix[SkMatrix::kMScaleX];
|
||||
SkScalar b = viewMatrix[SkMatrix::kMSkewX];
|
||||
SkScalar c = viewMatrix[SkMatrix::kMSkewY];
|
||||
SkScalar d = viewMatrix[SkMatrix::kMScaleY];
|
||||
SkScalar geoDx = SK_ScalarHalf / SkScalarSqrt(a*a + c*c);
|
||||
SkScalar geoDy = SK_ScalarHalf / SkScalarSqrt(b*b + d*d);
|
||||
|
||||
DIEllipseBatch* batch = new DIEllipseBatch();
|
||||
batch->fGeoData.emplace_back(Geometry {
|
||||
viewMatrix,
|
||||
color,
|
||||
xRadius,
|
||||
yRadius,
|
||||
innerXRadius,
|
||||
innerYRadius,
|
||||
geoDx,
|
||||
geoDy,
|
||||
dieStyle,
|
||||
SkRect::MakeLTRB(center.fX - xRadius - geoDx, center.fY - yRadius - geoDy,
|
||||
center.fX + xRadius + geoDx, center.fY + yRadius + geoDy)
|
||||
});
|
||||
SkRect devBounds = batch->fGeoData.back().fBounds;
|
||||
viewMatrix.mapRect(&devBounds);
|
||||
batch->setBounds(devBounds);
|
||||
return batch;
|
||||
}
|
||||
|
||||
const char* name() const override { return "DIEllipseBatch"; }
|
||||
@ -999,6 +1009,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
DIEllipseBatch() : INHERITED(ClassID()) {}
|
||||
|
||||
void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
|
||||
// Handle any overrides that affect our GP.
|
||||
overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
|
||||
@ -1061,12 +1073,6 @@ private:
|
||||
helper.recordDraw(target, gp);
|
||||
}
|
||||
|
||||
DIEllipseBatch(const Geometry& geometry, const SkRect& bounds) : INHERITED(ClassID()) {
|
||||
fGeoData.push_back(geometry);
|
||||
|
||||
this->setBounds(bounds);
|
||||
}
|
||||
|
||||
bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
|
||||
DIEllipseBatch* that = t->cast<DIEllipseBatch>();
|
||||
if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
|
||||
@ -1091,96 +1097,25 @@ private:
|
||||
const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
|
||||
DIEllipseStyle style() const { return fGeoData[0].fStyle; }
|
||||
|
||||
struct Geometry {
|
||||
SkMatrix fViewMatrix;
|
||||
GrColor fColor;
|
||||
SkScalar fXRadius;
|
||||
SkScalar fYRadius;
|
||||
SkScalar fInnerXRadius;
|
||||
SkScalar fInnerYRadius;
|
||||
SkScalar fGeoDx;
|
||||
SkScalar fGeoDy;
|
||||
DIEllipseStyle fStyle;
|
||||
SkRect fBounds;
|
||||
};
|
||||
|
||||
bool fUsesLocalCoords;
|
||||
SkSTArray<1, Geometry, true> fGeoData;
|
||||
|
||||
typedef GrVertexBatch INHERITED;
|
||||
};
|
||||
|
||||
static GrDrawBatch* create_diellipse_batch(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& ellipse,
|
||||
const SkStrokeRec& stroke) {
|
||||
SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
|
||||
SkScalar xRadius = SkScalarHalf(ellipse.width());
|
||||
SkScalar yRadius = SkScalarHalf(ellipse.height());
|
||||
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
DIEllipseStyle dieStyle = (SkStrokeRec::kStroke_Style == style) ?
|
||||
DIEllipseStyle::kStroke :
|
||||
(SkStrokeRec::kHairline_Style == style) ?
|
||||
DIEllipseStyle::kHairline : DIEllipseStyle::kFill;
|
||||
|
||||
SkScalar innerXRadius = 0;
|
||||
SkScalar innerYRadius = 0;
|
||||
if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != style) {
|
||||
SkScalar strokeWidth = stroke.getWidth();
|
||||
|
||||
if (SkScalarNearlyZero(strokeWidth)) {
|
||||
strokeWidth = SK_ScalarHalf;
|
||||
} else {
|
||||
strokeWidth *= SK_ScalarHalf;
|
||||
}
|
||||
|
||||
// we only handle thick strokes for near-circular ellipses
|
||||
if (strokeWidth > SK_ScalarHalf &&
|
||||
(SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we don't handle it if curvature of the stroke is less than curvature of the ellipse
|
||||
if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius ||
|
||||
strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// set inner radius (if needed)
|
||||
if (SkStrokeRec::kStroke_Style == style) {
|
||||
innerXRadius = xRadius - strokeWidth;
|
||||
innerYRadius = yRadius - strokeWidth;
|
||||
}
|
||||
|
||||
xRadius += strokeWidth;
|
||||
yRadius += strokeWidth;
|
||||
}
|
||||
if (DIEllipseStyle::kStroke == dieStyle) {
|
||||
dieStyle = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseStyle ::kStroke :
|
||||
DIEllipseStyle ::kFill;
|
||||
}
|
||||
|
||||
// This expands the outer rect so that after CTM we end up with a half-pixel border
|
||||
SkScalar a = viewMatrix[SkMatrix::kMScaleX];
|
||||
SkScalar b = viewMatrix[SkMatrix::kMSkewX];
|
||||
SkScalar c = viewMatrix[SkMatrix::kMSkewY];
|
||||
SkScalar d = viewMatrix[SkMatrix::kMScaleY];
|
||||
SkScalar geoDx = SK_ScalarHalf / SkScalarSqrt(a*a + c*c);
|
||||
SkScalar geoDy = SK_ScalarHalf / SkScalarSqrt(b*b + d*d);
|
||||
|
||||
DIEllipseBatch::Geometry geometry;
|
||||
geometry.fViewMatrix = viewMatrix;
|
||||
geometry.fColor = color;
|
||||
geometry.fXRadius = xRadius;
|
||||
geometry.fYRadius = yRadius;
|
||||
geometry.fInnerXRadius = innerXRadius;
|
||||
geometry.fInnerYRadius = innerYRadius;
|
||||
geometry.fGeoDx = geoDx;
|
||||
geometry.fGeoDy = geoDy;
|
||||
geometry.fStyle = dieStyle;
|
||||
geometry.fBounds = SkRect::MakeLTRB(center.fX - xRadius - geoDx, center.fY - yRadius - geoDy,
|
||||
center.fX + xRadius + geoDx, center.fY + yRadius + geoDy);
|
||||
|
||||
SkRect devBounds = geometry.fBounds;
|
||||
viewMatrix.mapRect(&devBounds);
|
||||
return DIEllipseBatch::Create(geometry, devBounds);
|
||||
}
|
||||
|
||||
GrDrawBatch* GrOvalRenderer::CreateDIEllipseBatch(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& ellipse,
|
||||
const SkStrokeRec& stroke) {
|
||||
return create_diellipse_batch(color, viewMatrix, ellipse, stroke);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const uint16_t gRRectIndices[] = {
|
||||
@ -1230,20 +1165,46 @@ class RRectCircleRendererBatch : public GrVertexBatch {
|
||||
public:
|
||||
DEFINE_BATCH_CLASS_ID
|
||||
|
||||
struct Geometry {
|
||||
SkRect fDevBounds;
|
||||
SkScalar fInnerRadius;
|
||||
SkScalar fOuterRadius;
|
||||
GrColor fColor;
|
||||
};
|
||||
// A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then strokeOnly indicates
|
||||
// whether the rrect is only stroked or stroked and filled.
|
||||
RRectCircleRendererBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& devRect,
|
||||
float devRadius, float devStrokeWidth, bool strokeOnly)
|
||||
: INHERITED(ClassID())
|
||||
, fViewMatrixIfUsingLocalCoords(viewMatrix) {
|
||||
SkRect bounds = devRect;
|
||||
SkASSERT(!(devStrokeWidth <= 0 && strokeOnly));
|
||||
SkScalar innerRadius = 0.0f;
|
||||
SkScalar outerRadius = devRadius;
|
||||
SkScalar halfWidth = 0;
|
||||
fStroked = false;
|
||||
if (devStrokeWidth > 0) {
|
||||
if (SkScalarNearlyZero(devStrokeWidth)) {
|
||||
halfWidth = SK_ScalarHalf;
|
||||
} else {
|
||||
halfWidth = SkScalarHalf(devStrokeWidth);
|
||||
}
|
||||
|
||||
RRectCircleRendererBatch(const Geometry& geometry, const SkMatrix& viewMatrix, bool stroked)
|
||||
: INHERITED(ClassID())
|
||||
, fStroked(stroked)
|
||||
, fViewMatrixIfUsingLocalCoords(viewMatrix) {
|
||||
fGeoData.push_back(geometry);
|
||||
if (strokeOnly) {
|
||||
innerRadius = devRadius - halfWidth;
|
||||
fStroked = innerRadius >= 0;
|
||||
}
|
||||
outerRadius += halfWidth;
|
||||
bounds.outset(halfWidth, halfWidth);
|
||||
}
|
||||
|
||||
this->setBounds(geometry.fDevBounds);
|
||||
// The radii are outset for two reasons. First, it allows the shader to simply perform
|
||||
// simpler computation because the computed alpha is zero, rather than 50%, at the radius.
|
||||
// Second, the outer radius is used to compute the verts of the bounding box that is
|
||||
// rendered and the outset ensures the box will cover all partially covered by the rrect
|
||||
// corners.
|
||||
outerRadius += SK_ScalarHalf;
|
||||
innerRadius -= SK_ScalarHalf;
|
||||
|
||||
// Expand the rect so all the pixels will be captured.
|
||||
bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
|
||||
|
||||
fGeoData.emplace_back(Geometry { color, innerRadius, outerRadius, bounds });
|
||||
this->setBounds(bounds);
|
||||
}
|
||||
|
||||
const char* name() const override { return "RRectCircleBatch"; }
|
||||
@ -1365,6 +1326,13 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Geometry {
|
||||
GrColor fColor;
|
||||
SkScalar fInnerRadius;
|
||||
SkScalar fOuterRadius;
|
||||
SkRect fDevBounds;
|
||||
};
|
||||
|
||||
bool fStroked;
|
||||
SkMatrix fViewMatrixIfUsingLocalCoords;
|
||||
SkSTArray<1, Geometry, true> fGeoData;
|
||||
@ -1376,21 +1344,64 @@ class RRectEllipseRendererBatch : public GrVertexBatch {
|
||||
public:
|
||||
DEFINE_BATCH_CLASS_ID
|
||||
|
||||
struct Geometry {
|
||||
SkRect fDevBounds;
|
||||
SkScalar fXRadius;
|
||||
SkScalar fYRadius;
|
||||
SkScalar fInnerXRadius;
|
||||
SkScalar fInnerYRadius;
|
||||
GrColor fColor;
|
||||
};
|
||||
// If devStrokeWidths values are <= 0 indicates then fill only. Otherwise, strokeOnly indicates
|
||||
// whether the rrect is only stroked or stroked and filled.
|
||||
static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& devRect,
|
||||
float devXRadius, float devYRadius, SkVector devStrokeWidths,
|
||||
bool strokeOnly) {
|
||||
SkASSERT(devXRadius > 0.5);
|
||||
SkASSERT(devYRadius > 0.5);
|
||||
SkASSERT((devStrokeWidths.fX > 0) == (devStrokeWidths.fY > 0));
|
||||
SkASSERT(!(strokeOnly && devStrokeWidths.fX <= 0));
|
||||
SkScalar innerXRadius = 0.0f;
|
||||
SkScalar innerYRadius = 0.0f;
|
||||
SkRect bounds = devRect;
|
||||
bool stroked = false;
|
||||
if (devStrokeWidths.fX > 0) {
|
||||
if (SkScalarNearlyZero(devStrokeWidths.length())) {
|
||||
devStrokeWidths.set(SK_ScalarHalf, SK_ScalarHalf);
|
||||
} else {
|
||||
devStrokeWidths.scale(SK_ScalarHalf);
|
||||
}
|
||||
|
||||
RRectEllipseRendererBatch(const Geometry& geometry, const SkMatrix& viewMatrix, bool stroked)
|
||||
: INHERITED(ClassID())
|
||||
, fStroked(stroked)
|
||||
, fViewMatrixIfUsingLocalCoords(viewMatrix) {
|
||||
fGeoData.push_back(geometry);
|
||||
this->setBounds(geometry.fDevBounds);
|
||||
// we only handle thick strokes for near-circular ellipses
|
||||
if (devStrokeWidths.length() > SK_ScalarHalf &&
|
||||
(SK_ScalarHalf*devXRadius > devYRadius || SK_ScalarHalf*devYRadius > devXRadius)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we don't handle it if curvature of the stroke is less than curvature of the ellipse
|
||||
if (devStrokeWidths.fX*(devYRadius*devYRadius) <
|
||||
(devStrokeWidths.fY*devStrokeWidths.fY)*devXRadius) {
|
||||
return nullptr;
|
||||
}
|
||||
if (devStrokeWidths.fY*(devXRadius*devXRadius) <
|
||||
(devStrokeWidths.fX*devStrokeWidths.fX)*devYRadius) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// this is legit only if scale & translation (which should be the case at the moment)
|
||||
if (strokeOnly) {
|
||||
innerXRadius = devXRadius - devStrokeWidths.fX;
|
||||
innerYRadius = devYRadius - devStrokeWidths.fY;
|
||||
stroked = (innerXRadius >= 0 && innerYRadius >= 0);
|
||||
}
|
||||
|
||||
devXRadius += devStrokeWidths.fX;
|
||||
devYRadius += devStrokeWidths.fY;
|
||||
bounds.outset(devStrokeWidths.fX, devStrokeWidths.fY);
|
||||
}
|
||||
|
||||
// Expand the rect so all the pixels will be captured.
|
||||
bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
|
||||
|
||||
RRectEllipseRendererBatch* batch = new RRectEllipseRendererBatch();
|
||||
batch->fStroked = stroked;
|
||||
batch->fViewMatrixIfUsingLocalCoords = viewMatrix;
|
||||
batch->fGeoData.emplace_back(
|
||||
Geometry {color, devXRadius, devYRadius, innerXRadius, innerYRadius, bounds});
|
||||
batch->setBounds(bounds);
|
||||
return batch;
|
||||
}
|
||||
|
||||
const char* name() const override { return "RRectEllipseRendererBatch"; }
|
||||
@ -1404,6 +1415,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
RRectEllipseRendererBatch() : INHERITED(ClassID()) {}
|
||||
|
||||
void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
|
||||
// Handle overrides that affect our GP.
|
||||
overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
|
||||
@ -1523,6 +1536,15 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Geometry {
|
||||
GrColor fColor;
|
||||
SkScalar fXRadius;
|
||||
SkScalar fYRadius;
|
||||
SkScalar fInnerXRadius;
|
||||
SkScalar fInnerYRadius;
|
||||
SkRect fDevBounds;
|
||||
};
|
||||
|
||||
bool fStroked;
|
||||
SkMatrix fViewMatrixIfUsingLocalCoords;
|
||||
SkSTArray<1, Geometry, true> fGeoData;
|
||||
@ -1552,8 +1574,8 @@ static GrDrawBatch* create_rrect_batch(GrColor color,
|
||||
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
|
||||
// do (potentially) anisotropic mapping of stroke
|
||||
SkVector scaledStroke;
|
||||
// Do (potentially) anisotropic mapping of stroke. Use -1s to indicate fill-only draws.
|
||||
SkVector scaledStroke = {-1, -1};
|
||||
SkScalar strokeWidth = stroke.getWidth();
|
||||
|
||||
bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
|
||||
@ -1587,91 +1609,13 @@ static GrDrawBatch* create_rrect_batch(GrColor color,
|
||||
|
||||
// if the corners are circles, use the circle renderer
|
||||
if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) {
|
||||
SkScalar innerRadius = 0.0f;
|
||||
SkScalar outerRadius = xRadius;
|
||||
SkScalar halfWidth = 0;
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(scaledStroke.fX)) {
|
||||
halfWidth = SK_ScalarHalf;
|
||||
} else {
|
||||
halfWidth = SkScalarHalf(scaledStroke.fX);
|
||||
}
|
||||
|
||||
if (isStrokeOnly) {
|
||||
innerRadius = xRadius - halfWidth;
|
||||
}
|
||||
outerRadius += halfWidth;
|
||||
bounds.outset(halfWidth, halfWidth);
|
||||
}
|
||||
|
||||
isStrokeOnly = (isStrokeOnly && innerRadius >= 0);
|
||||
|
||||
// The radii are outset for two reasons. First, it allows the shader to simply perform
|
||||
// simpler computation because the computed alpha is zero, rather than 50%, at the radius.
|
||||
// Second, the outer radius is used to compute the verts of the bounding box that is
|
||||
// rendered and the outset ensures the box will cover all partially covered by the rrect
|
||||
// corners.
|
||||
outerRadius += SK_ScalarHalf;
|
||||
innerRadius -= SK_ScalarHalf;
|
||||
|
||||
// Expand the rect so all the pixels will be captured.
|
||||
bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
|
||||
|
||||
RRectCircleRendererBatch::Geometry geometry;
|
||||
geometry.fColor = color;
|
||||
geometry.fInnerRadius = innerRadius;
|
||||
geometry.fOuterRadius = outerRadius;
|
||||
geometry.fDevBounds = bounds;
|
||||
|
||||
return new RRectCircleRendererBatch(geometry, viewMatrix, isStrokeOnly);
|
||||
return new RRectCircleRendererBatch(color, viewMatrix, bounds, xRadius, scaledStroke.fX,
|
||||
isStrokeOnly);
|
||||
// otherwise we use the ellipse renderer
|
||||
} else {
|
||||
SkScalar innerXRadius = 0.0f;
|
||||
SkScalar innerYRadius = 0.0f;
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(scaledStroke.length())) {
|
||||
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
|
||||
} else {
|
||||
scaledStroke.scale(SK_ScalarHalf);
|
||||
}
|
||||
return RRectEllipseRendererBatch::Create(color, viewMatrix, bounds, xRadius, yRadius,
|
||||
scaledStroke, isStrokeOnly);
|
||||
|
||||
// we only handle thick strokes for near-circular ellipses
|
||||
if (scaledStroke.length() > SK_ScalarHalf &&
|
||||
(SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we don't handle it if curvature of the stroke is less than curvature of the ellipse
|
||||
if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius ||
|
||||
scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// this is legit only if scale & translation (which should be the case at the moment)
|
||||
if (isStrokeOnly) {
|
||||
innerXRadius = xRadius - scaledStroke.fX;
|
||||
innerYRadius = yRadius - scaledStroke.fY;
|
||||
}
|
||||
|
||||
xRadius += scaledStroke.fX;
|
||||
yRadius += scaledStroke.fY;
|
||||
bounds.outset(scaledStroke.fX, scaledStroke.fY);
|
||||
}
|
||||
|
||||
isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0);
|
||||
|
||||
// Expand the rect so all the pixels will be captured.
|
||||
bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
|
||||
|
||||
RRectEllipseRendererBatch::Geometry geometry;
|
||||
geometry.fColor = color;
|
||||
geometry.fXRadius = xRadius;
|
||||
geometry.fYRadius = yRadius;
|
||||
geometry.fInnerXRadius = innerXRadius;
|
||||
geometry.fInnerYRadius = innerYRadius;
|
||||
geometry.fDevBounds = bounds;
|
||||
|
||||
return new RRectEllipseRendererBatch(geometry, viewMatrix, isStrokeOnly);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1691,7 +1635,32 @@ GrDrawBatch* GrOvalRenderer::CreateRRectBatch(GrColor color,
|
||||
return create_rrect_batch(color, viewMatrix, rrect, stroke);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrDrawBatch* GrOvalRenderer::CreateOvalBatch(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& oval,
|
||||
const SkStrokeRec& stroke,
|
||||
GrShaderCaps* shaderCaps) {
|
||||
// we can draw circles
|
||||
if (SkScalarNearlyEqual(oval.width(), oval.height()) && circle_stays_circle(viewMatrix)) {
|
||||
return new CircleBatch(color, viewMatrix, oval, stroke);
|
||||
}
|
||||
|
||||
// if we have shader derivative support, render as device-independent
|
||||
if (shaderCaps->shaderDerivativeSupport()) {
|
||||
return DIEllipseBatch::Create(color, viewMatrix, oval, stroke);
|
||||
}
|
||||
|
||||
// otherwise axis-aligned ellipses only
|
||||
if (viewMatrix.rectStaysRect()) {
|
||||
return EllipseBatch::Create(color, viewMatrix, oval, stroke);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef GR_TEST_UTILS
|
||||
|
||||
@ -1699,21 +1668,21 @@ DRAW_BATCH_TEST_DEFINE(CircleBatch) {
|
||||
SkMatrix viewMatrix = GrTest::TestMatrix(random);
|
||||
GrColor color = GrRandomColor(random);
|
||||
SkRect circle = GrTest::TestSquare(random);
|
||||
return create_circle_batch(color, viewMatrix, circle, GrTest::TestStrokeRec(random));
|
||||
return new CircleBatch(color, viewMatrix, circle, GrTest::TestStrokeRec(random));
|
||||
}
|
||||
|
||||
DRAW_BATCH_TEST_DEFINE(EllipseBatch) {
|
||||
SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
|
||||
GrColor color = GrRandomColor(random);
|
||||
SkRect ellipse = GrTest::TestSquare(random);
|
||||
return create_ellipse_batch(color, viewMatrix, ellipse, GrTest::TestStrokeRec(random));
|
||||
return EllipseBatch::Create(color, viewMatrix, ellipse, GrTest::TestStrokeRec(random));
|
||||
}
|
||||
|
||||
DRAW_BATCH_TEST_DEFINE(DIEllipseBatch) {
|
||||
SkMatrix viewMatrix = GrTest::TestMatrix(random);
|
||||
GrColor color = GrRandomColor(random);
|
||||
SkRect ellipse = GrTest::TestSquare(random);
|
||||
return create_diellipse_batch(color, viewMatrix, ellipse, GrTest::TestStrokeRec(random));
|
||||
return DIEllipseBatch::Create(color, viewMatrix, ellipse, GrTest::TestStrokeRec(random));
|
||||
}
|
||||
|
||||
DRAW_BATCH_TEST_DEFINE(RRectBatch) {
|
||||
|
@ -35,19 +35,6 @@ public:
|
||||
|
||||
private:
|
||||
GrOvalRenderer();
|
||||
|
||||
static GrDrawBatch* CreateEllipseBatch(GrColor,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& ellipse,
|
||||
const SkStrokeRec& stroke);
|
||||
static GrDrawBatch* CreateDIEllipseBatch(GrColor,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& ellipse,
|
||||
const SkStrokeRec& stroke);
|
||||
static GrDrawBatch* CreateCircleBatch(GrColor,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& circle,
|
||||
const SkStrokeRec& stroke);
|
||||
};
|
||||
|
||||
#endif // GrOvalRenderer_DEFINED
|
||||
|
Loading…
Reference in New Issue
Block a user