aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/gpu.gypi2
-rw-r--r--src/gpu/GrBatchTest.cpp2
-rw-r--r--src/gpu/GrDrawContext.cpp4
-rw-r--r--src/gpu/batches/GrAnalyticRectBatch.cpp414
-rw-r--r--src/gpu/batches/GrAnalyticRectBatch.h36
-rw-r--r--src/gpu/batches/GrRectBatchFactory.h12
6 files changed, 466 insertions, 4 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 4f4ff3546f..a856cb495b 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -219,6 +219,8 @@
'<(skia_src_path)/gpu/batches/GrAAFillRectBatch.h',
'<(skia_src_path)/gpu/batches/GrAAStrokeRectBatch.cpp',
'<(skia_src_path)/gpu/batches/GrAAStrokeRectBatch.h',
+ '<(skia_src_path)/gpu/batches/GrAnalyticRectBatch.cpp',
+ '<(skia_src_path)/gpu/batches/GrAnalyticRectBatch.h',
'<(skia_src_path)/gpu/batches/GrAtlasTextBatch.cpp',
'<(skia_src_path)/gpu/batches/GrAtlasTextBatch.h',
'<(skia_src_path)/gpu/batches/GrBatch.cpp',
diff --git a/src/gpu/GrBatchTest.cpp b/src/gpu/GrBatchTest.cpp
index 344464d717..fe320a268a 100644
--- a/src/gpu/GrBatchTest.cpp
+++ b/src/gpu/GrBatchTest.cpp
@@ -17,6 +17,7 @@ DRAW_BATCH_TEST_EXTERN(AAFillRectBatch);
DRAW_BATCH_TEST_EXTERN(AAFillRectBatchLocalMatrix);
DRAW_BATCH_TEST_EXTERN(AAHairlineBatch);
DRAW_BATCH_TEST_EXTERN(AAStrokeRectBatch);
+DRAW_BATCH_TEST_EXTERN(AnalyticRectBatch);
DRAW_BATCH_TEST_EXTERN(DashBatch);
DRAW_BATCH_TEST_EXTERN(DefaultPathBatch);
DRAW_BATCH_TEST_EXTERN(CircleBatch);
@@ -36,6 +37,7 @@ static BatchTestFunc gTestBatches[] = {
DRAW_BATCH_TEST_ENTRY(AAFillRectBatchLocalMatrix),
DRAW_BATCH_TEST_ENTRY(AAHairlineBatch),
DRAW_BATCH_TEST_ENTRY(AAStrokeRectBatch),
+ DRAW_BATCH_TEST_ENTRY(AnalyticRectBatch),
DRAW_BATCH_TEST_ENTRY(DashBatch),
DRAW_BATCH_TEST_ENTRY(DefaultPathBatch),
DRAW_BATCH_TEST_ENTRY(CircleBatch),
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index fe8730e60f..d73097a816 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -385,8 +385,8 @@ bool GrDrawContext::drawFilledRect(const GrClip& clip,
SkRect devBoundRect;
viewMatrix.mapRect(&devBoundRect, croppedRect);
- batch.reset(GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix,
- croppedRect, devBoundRect));
+ batch.reset(GrRectBatchFactory::CreateAAFill(paint, viewMatrix, rect, croppedRect,
+ devBoundRect));
if (batch) {
GrPipelineBuilder pipelineBuilder(paint, useHWAA);
if (ss) {
diff --git a/src/gpu/batches/GrAnalyticRectBatch.cpp b/src/gpu/batches/GrAnalyticRectBatch.cpp
new file mode 100644
index 0000000000..b41aa7f719
--- /dev/null
+++ b/src/gpu/batches/GrAnalyticRectBatch.cpp
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrAnalyticRectBatch.h"
+
+#include "GrBatchFlushState.h"
+#include "GrBatchTest.h"
+#include "GrGeometryProcessor.h"
+#include "GrInvariantOutput.h"
+#include "GrProcessor.h"
+#include "GrResourceProvider.h"
+#include "SkRRect.h"
+#include "SkStrokeRec.h"
+#include "batches/GrVertexBatch.h"
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "glsl/GrGLSLGeometryProcessor.h"
+#include "glsl/GrGLSLProgramDataManager.h"
+#include "glsl/GrGLSLVarying.h"
+#include "glsl/GrGLSLVertexShaderBuilder.h"
+#include "glsl/GrGLSLUniformHandler.h"
+#include "glsl/GrGLSLUtil.h"
+
+namespace {
+
+struct RectVertex {
+ SkPoint fPos;
+ GrColor fColor;
+ SkPoint fCenter;
+ SkVector fDownDir;
+ SkScalar fHalfWidth;
+ SkScalar fHalfHeight;
+};
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * The output of this effect is the input color and coverage for an arbitrarily oriented rect. The
+ * rect is specified as:
+ * Center of the rect
+ * Unit vector point down the height of the rect
+ * Half width + 0.5
+ * Half height + 0.5
+ * The center and vector are stored in a vec4 varying ("RectEdge") with the
+ * center in the xy components and the vector in the zw components.
+ * The munged width and height are stored in a vec2 varying ("WidthHeight")
+ * with the width in x and the height in y.
+ */
+class RectGeometryProcessor : public GrGeometryProcessor {
+public:
+ RectGeometryProcessor(const SkMatrix& localMatrix) : fLocalMatrix(localMatrix) {
+ this->initClassID<RectGeometryProcessor>();
+ fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
+ kHigh_GrSLPrecision));
+ fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
+ fInRectEdge = &this->addVertexAttrib(Attribute("inRectEdge", kVec4f_GrVertexAttribType));
+ fInWidthHeight = &this->addVertexAttrib(Attribute("inWidthHeight",
+ kVec2f_GrVertexAttribType));
+ }
+
+ bool implementsDistanceVector() const override { return true; };
+
+ const Attribute* inPosition() const { return fInPosition; }
+ const Attribute* inColor() const { return fInColor; }
+ const Attribute* inRectEdge() const { return fInRectEdge; }
+ const Attribute* inWidthHeight() const { return fInWidthHeight; }
+
+ const SkMatrix& localMatrix() const { return fLocalMatrix; }
+
+ virtual ~RectGeometryProcessor() {}
+
+ const char* name() const override { return "RectEdge"; }
+
+ class GLSLProcessor : public GrGLSLGeometryProcessor {
+ public:
+ GLSLProcessor() {}
+
+ void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
+ const RectGeometryProcessor& rgp = args.fGP.cast<RectGeometryProcessor>();
+ GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
+ GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
+ GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
+
+ // emit attributes
+ varyingHandler->emitAttributes(rgp);
+
+ // setup the varying for the position
+ GrGLSLVertToFrag positionVary(kVec2f_GrSLType);
+ varyingHandler->addVarying("Position", &positionVary);
+ vertBuilder->codeAppendf("%s = %s;", positionVary.vsOut(), rgp.inPosition()->fName);
+
+ // setup the varying for the center point and the unit vector that points down the
+ // height of the rect
+ GrGLSLVertToFrag rectEdgeVary(kVec4f_GrSLType);
+ varyingHandler->addVarying("RectEdge", &rectEdgeVary);
+ vertBuilder->codeAppendf("%s = %s;", rectEdgeVary.vsOut(), rgp.inRectEdge()->fName);
+
+ // setup the varying for the width/2+.5 and height/2+.5
+ GrGLSLVertToFrag widthHeightVary(kVec2f_GrSLType);
+ varyingHandler->addVarying("WidthHeight", &widthHeightVary);
+ vertBuilder->codeAppendf("%s = %s;",
+ widthHeightVary.vsOut(), rgp.inWidthHeight()->fName);
+
+ GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
+
+ // setup pass through color
+ varyingHandler->addPassThroughAttribute(rgp.inColor(), args.fOutputColor);
+
+ // Setup position
+ this->setupPosition(vertBuilder, gpArgs, rgp.inPosition()->fName);
+
+ // emit transforms
+ this->emitTransforms(vertBuilder,
+ varyingHandler,
+ uniformHandler,
+ gpArgs->fPositionVar,
+ rgp.inPosition()->fName,
+ rgp.localMatrix(),
+ args.fTransformsIn,
+ args.fTransformsOut);
+
+ // TODO: compute all these offsets, spans, and scales in the VS
+ fragBuilder->codeAppendf("float insetW = min(1.0, %s.x) - 0.5;",
+ widthHeightVary.fsIn());
+ fragBuilder->codeAppendf("float insetH = min(1.0, %s.y) - 0.5;",
+ widthHeightVary.fsIn());
+ fragBuilder->codeAppend("float outset = 0.5;");
+ // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects
+ // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range.
+ fragBuilder->codeAppend("float spanW = insetW + outset;");
+ fragBuilder->codeAppend("float spanH = insetH + outset;");
+ // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum
+ // value of coverage that is used. In other words it is the coverage that is
+ // used in the interior of the rect after the ramp.
+ fragBuilder->codeAppend("float scaleW = min(1.0, 2.0*insetW/spanW);");
+ fragBuilder->codeAppend("float scaleH = min(1.0, 2.0*insetH/spanH);");
+ // Compute the coverage for the rect's width
+ fragBuilder->codeAppendf("vec2 offset = %s.xy - %s.xy;",
+ positionVary.fsIn(), rectEdgeVary.fsIn());
+ fragBuilder->codeAppendf("float perpDot = abs(offset.x * %s.w - offset.y * %s.z);",
+ rectEdgeVary.fsIn(), rectEdgeVary.fsIn());
+
+ if (args.fDistanceVectorName) {
+ fragBuilder->codeAppendf("float widthDistance = %s.x - perpDot;",
+ widthHeightVary.fsIn());
+ }
+
+ fragBuilder->codeAppendf(
+ "float coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0);",
+ widthHeightVary.fsIn());
+ // Compute the coverage for the rect's height and merge with the width
+ fragBuilder->codeAppendf("perpDot = abs(dot(offset, %s.zw));",
+ rectEdgeVary.fsIn());
+
+ if (args.fDistanceVectorName) {
+ fragBuilder->codeAppendf("float heightDistance = %s.y - perpDot;",
+ widthHeightVary.fsIn());
+ }
+
+ fragBuilder->codeAppendf(
+ "coverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);",
+ widthHeightVary.fsIn());
+
+ fragBuilder->codeAppendf("%s = vec4(coverage);", args.fOutputCoverage);
+
+ if (args.fDistanceVectorName) {
+ fragBuilder->codeAppend( "// Calculating distance vector\n");
+ fragBuilder->codeAppend( "vec2 dvAxis;");
+ fragBuilder->codeAppend( "float dvLength;");
+
+ fragBuilder->codeAppend( "if (heightDistance < widthDistance) {");
+ fragBuilder->codeAppendf(" dvAxis = %s.zw;", rectEdgeVary.fsIn());
+ fragBuilder->codeAppend( " dvLength = heightDistance;");
+ fragBuilder->codeAppend( "} else {");
+ fragBuilder->codeAppendf(" dvAxis = vec2(-%s.w, %s.z);",
+ rectEdgeVary.fsIn(), rectEdgeVary.fsIn());
+ fragBuilder->codeAppend( " dvLength = widthDistance;");
+ fragBuilder->codeAppend( "}");
+
+ fragBuilder->codeAppend( "float dvSign = sign(dot(offset, dvAxis));");
+ fragBuilder->codeAppendf("%s = vec3(dvSign * dvAxis, dvLength);",
+ args.fDistanceVectorName);
+
+ }
+ }
+
+ static void GenKey(const GrGeometryProcessor& gp,
+ const GrGLSLCaps&,
+ GrProcessorKeyBuilder* b) {
+ b->add32(0x0);
+ }
+
+ void setData(const GrGLSLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& gp) override {}
+
+ void setTransformData(const GrPrimitiveProcessor& primProc,
+ const GrGLSLProgramDataManager& pdman,
+ int index,
+ const SkTArray<const GrCoordTransform*, true>& transforms) override {
+ this->setTransformDataHelper<RectGeometryProcessor>(primProc, pdman, index, transforms);
+ }
+
+ private:
+ typedef GrGLSLGeometryProcessor INHERITED;
+ };
+
+ void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
+ GLSLProcessor::GenKey(*this, caps, b);
+ }
+
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const override {
+ return new GLSLProcessor();
+ }
+
+private:
+ SkMatrix fLocalMatrix;
+
+ const Attribute* fInPosition;
+ const Attribute* fInColor;
+ const Attribute* fInRectEdge;
+ const Attribute* fInWidthHeight;
+
+ GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
+
+ typedef GrGeometryProcessor INHERITED;
+};
+
+GR_DEFINE_GEOMETRY_PROCESSOR_TEST(RectGeometryProcessor);
+
+sk_sp<GrGeometryProcessor> RectGeometryProcessor::TestCreate(GrProcessorTestData* d) {
+ return sk_sp<GrGeometryProcessor>(
+ new RectGeometryProcessor(GrTest::TestMatrix(d->fRandom)));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class AnalyticRectBatch : public GrVertexBatch {
+public:
+ DEFINE_BATCH_CLASS_ID
+
+ AnalyticRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
+ const SkRect& croppedRect, const SkRect& bounds)
+ : INHERITED(ClassID())
+ , fViewMatrixIfUsingLocalCoords(viewMatrix) {
+ SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY());
+ viewMatrix.mapPoints(&center, 1);
+ SkScalar halfWidth = viewMatrix.mapRadius(SkScalarHalf(rect.width()));
+ SkScalar halfHeight = viewMatrix.mapRadius(SkScalarHalf(rect.height()));
+ SkVector downDir = viewMatrix.mapVector(0.0f, 1.0f);
+ downDir.normalize();
+
+ SkRect deviceSpaceCroppedRect = croppedRect;
+ viewMatrix.mapRect(&deviceSpaceCroppedRect);
+
+ fGeoData.emplace_back(Geometry {color, center, downDir, halfWidth, halfHeight,
+ deviceSpaceCroppedRect});
+
+ this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo);
+ }
+
+ const char* name() const override { return "AnalyticRectBatch"; }
+
+ SkString dumpInfo() const override {
+ SkString string;
+ for (int i = 0; i < fGeoData.count(); ++i) {
+ string.appendf("Color: 0x%08x Rect [C:(%.2f, %.2f) D:<%.2f,%.3f> W/2:%.2f H/2:%.2f]\n",
+ fGeoData[i].fColor,
+ fGeoData[i].fCenter.x(), fGeoData[i].fCenter.y(),
+ fGeoData[i].fDownDir.x(), fGeoData[i].fDownDir.y(),
+ fGeoData[i].fHalfWidth,
+ fGeoData[i].fHalfHeight);
+ }
+ string.append(INHERITED::dumpInfo());
+ return string;
+ }
+
+ void computePipelineOptimizations(GrInitInvariantOutput* color,
+ GrInitInvariantOutput* coverage,
+ GrBatchToXPOverrides* overrides) const override {
+ // When this is called on a batch, there is only one geometry bundle
+ color->setKnownFourComponents(fGeoData[0].fColor);
+ coverage->setUnknownSingleComponent();
+ }
+
+private:
+ void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
+ // Handle any overrides that affect our GP.
+ overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
+ if (!overrides.readsLocalCoords()) {
+ fViewMatrixIfUsingLocalCoords.reset();
+ }
+ }
+
+ void onPrepareDraws(Target* target) const override {
+ SkMatrix localMatrix;
+ if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
+ return;
+ }
+
+ // Setup geometry processor
+ SkAutoTUnref<GrGeometryProcessor> gp(new RectGeometryProcessor(localMatrix));
+
+ int instanceCount = fGeoData.count();
+ size_t vertexStride = gp->getVertexStride();
+ SkASSERT(vertexStride == sizeof(RectVertex));
+ QuadHelper helper;
+ RectVertex* verts = reinterpret_cast<RectVertex*>(helper.init(target, vertexStride,
+ instanceCount));
+ if (!verts) {
+ return;
+ }
+
+ for (int i = 0; i < instanceCount; i++) {
+ const Geometry& geom = fGeoData[i];
+
+ GrColor color = geom.fColor;
+ SkPoint center = geom.fCenter;
+ SkVector downDir = geom.fDownDir;
+ SkScalar halfWidth = geom.fHalfWidth;
+ SkScalar halfHeight = geom.fHalfHeight;
+ SkRect croppedRect = geom.fCroppedRect;
+
+ SkVector rightDir;
+ downDir.rotateCCW(&rightDir);
+
+ verts[0].fPos = {croppedRect.fLeft, croppedRect.fTop};
+ verts[0].fColor = color;
+ verts[0].fCenter = center;
+ verts[0].fDownDir = downDir;
+ verts[0].fHalfWidth = halfWidth;
+ verts[0].fHalfHeight = halfHeight;
+
+ verts[1].fPos = {croppedRect.fRight, croppedRect.fTop};
+ verts[1].fColor = color;
+ verts[1].fCenter = center;
+ verts[1].fDownDir = downDir;
+ verts[1].fHalfWidth = halfWidth;
+ verts[1].fHalfHeight = halfHeight;
+
+ verts[2].fPos = {croppedRect.fRight, croppedRect.fBottom};
+ verts[2].fColor = color;
+ verts[2].fCenter = center;
+ verts[2].fDownDir = downDir;
+ verts[2].fHalfWidth = halfWidth;
+ verts[2].fHalfHeight = halfHeight;
+
+ verts[3].fPos = {croppedRect.fLeft, croppedRect.fBottom};
+ verts[3].fColor = color;
+ verts[3].fCenter = center;
+ verts[3].fDownDir = downDir;
+ verts[3].fHalfWidth = halfWidth;
+ verts[3].fHalfHeight = halfHeight;
+
+ verts += kVerticesPerQuad;
+ }
+ helper.recordDraw(target, gp);
+ }
+
+ bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
+ AnalyticRectBatch* that = t->cast<AnalyticRectBatch>();
+ if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
+ that->bounds(), caps)) {
+ return false;
+ }
+
+ if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
+ return false;
+ }
+
+ fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
+ this->joinBounds(*that);
+ return true;
+ }
+
+ struct Geometry {
+ GrColor fColor;
+ SkPoint fCenter;
+ SkVector fDownDir;
+ SkScalar fHalfWidth;
+ SkScalar fHalfHeight;
+ SkRect fCroppedRect;
+ };
+
+ SkMatrix fViewMatrixIfUsingLocalCoords;
+ SkSTArray<1, Geometry, true> fGeoData;
+
+ typedef GrVertexBatch INHERITED;
+};
+
+GrDrawBatch* GrAnalyticRectBatch::CreateAnalyticRectBatch(GrColor color,
+ const SkMatrix& viewMatrix,
+ const SkRect& rect,
+ const SkRect& croppedRect,
+ const SkRect& bounds) {
+ return new AnalyticRectBatch(color, viewMatrix, rect, croppedRect, bounds);
+}
+
+#ifdef GR_TEST_UTILS
+
+DRAW_BATCH_TEST_DEFINE(AnalyticRectBatch) {
+ SkMatrix viewMatrix = GrTest::TestMatrix(random);
+ GrColor color = GrRandomColor(random);
+ SkRect rect = GrTest::TestSquare(random);
+ SkRect croppedRect = GrTest::TestSquare(random);
+ SkRect bounds = GrTest::TestSquare(random);
+ return new AnalyticRectBatch(color, viewMatrix, rect, croppedRect, bounds);
+}
+
+#endif
diff --git a/src/gpu/batches/GrAnalyticRectBatch.h b/src/gpu/batches/GrAnalyticRectBatch.h
new file mode 100644
index 0000000000..cdb6118c6e
--- /dev/null
+++ b/src/gpu/batches/GrAnalyticRectBatch.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrAnalyticRectBatch_DEFINED
+#define GrAnalyticRectBatch_DEFINED
+
+#include "GrColor.h"
+
+class GrDrawBatch;
+class SkMatrix;
+struct SkRect;
+
+/*
+ * This class wraps helper functions that draw rects analytically. Used when a shader requires a
+ * distance vector.
+ *
+ * @param color the shape's color
+ * @param viewMatrix the shape's local matrix
+ * @param rect the shape in source space
+ * @param croppedRect the shape in device space, clipped to the device's bounds
+ * @param bounds the axis aligned bounds of the shape in device space
+ */
+class GrAnalyticRectBatch {
+public:
+ static GrDrawBatch* CreateAnalyticRectBatch(GrColor color,
+ const SkMatrix& viewMatrix,
+ const SkRect& rect,
+ const SkRect& croppedRect,
+ const SkRect& bounds);
+};
+
+#endif // GrAnalyticRectBatch_DEFINED
diff --git a/src/gpu/batches/GrRectBatchFactory.h b/src/gpu/batches/GrRectBatchFactory.h
index 4512f6a1f9..c9b6843596 100644
--- a/src/gpu/batches/GrRectBatchFactory.h
+++ b/src/gpu/batches/GrRectBatchFactory.h
@@ -10,9 +10,11 @@
#include "GrAAFillRectBatch.h"
#include "GrAAStrokeRectBatch.h"
+#include "GrAnalyticRectBatch.h"
#include "GrColor.h"
#include "GrNonAAFillRectBatch.h"
#include "GrNonAAStrokeRectBatch.h"
+#include "GrPaint.h"
#include "SkMatrix.h"
class GrBatch;
@@ -37,11 +39,17 @@ inline GrDrawBatch* CreateNonAAFill(GrColor color,
}
}
-inline GrDrawBatch* CreateAAFill(GrColor color,
+inline GrDrawBatch* CreateAAFill(const GrPaint& paint,
const SkMatrix& viewMatrix,
const SkRect& rect,
+ const SkRect& croppedRect,
const SkRect& devRect) {
- return GrAAFillRectBatch::Create(color, viewMatrix, rect, devRect);
+ if (!paint.usesDistanceVectorField()) {
+ return GrAAFillRectBatch::Create(paint.getColor(), viewMatrix, croppedRect, devRect);
+ } else {
+ return GrAnalyticRectBatch::CreateAnalyticRectBatch(paint.getColor(), viewMatrix, rect,
+ croppedRect, devRect);
+ }
}
inline GrDrawBatch* CreateAAFill(GrColor color,