blob: 1e3c64518b0b5b383d2071294493d5971c48ba9c [file] [log] [blame]
bsalomon@google.comffca4002011-02-22 20:34:01 +00001#include "GrPathRenderer.h"
2
3#include "GrPoint.h"
4#include "GrDrawTarget.h"
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +00005#include "GrPathUtils.h"
bsalomon@google.comffca4002011-02-22 20:34:01 +00006#include "GrTexture.h"
7
tomhudson@google.com278cbb42011-06-30 19:37:01 +00008#include "SkString.h"
bsalomon@google.com3582bf92011-06-30 21:32:31 +00009#include "SkTemplates.h"
10
tomhudson@google.com278cbb42011-06-30 19:37:01 +000011#include SK_USER_TRACE_INCLUDE_FILE
12
tomhudson@google.comd22b6e42011-06-24 15:53:40 +000013GrPathRenderer::GrPathRenderer()
14 : fCurveTolerance (GR_Scalar1) {
15
16}
17
bsalomon@google.comd302f142011-03-03 13:54:13 +000018GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
19 bool stencilWrapOpsSupport)
tomhudson@google.comd22b6e42011-06-24 15:53:40 +000020 : fSeparateStencil(separateStencilSupport)
21 , fStencilWrapOps(stencilWrapOpsSupport) {
bsalomon@google.comffca4002011-02-22 20:34:01 +000022
23}
24
25////////////////////////////////////////////////////////////////////////////////
bsalomon@google.comd302f142011-03-03 13:54:13 +000026// Stencil rules for paths
27
28////// Even/Odd
29
30static const GrStencilSettings gEOStencilPass = {
31 kInvert_StencilOp, kInvert_StencilOp,
32 kKeep_StencilOp, kKeep_StencilOp,
33 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
34 0xffffffff, 0xffffffff,
35 0xffffffff, 0xffffffff,
36 0xffffffff, 0xffffffff
37};
38
39// ok not to check clip b/c stencil pass only wrote inside clip
40static const GrStencilSettings gEOColorPass = {
41 kZero_StencilOp, kZero_StencilOp,
42 kZero_StencilOp, kZero_StencilOp,
43 kNotEqual_StencilFunc, kNotEqual_StencilFunc,
44 0xffffffff, 0xffffffff,
45 0x0, 0x0,
46 0xffffffff, 0xffffffff
47};
48
49// have to check clip b/c outside clip will always be zero.
50static const GrStencilSettings gInvEOColorPass = {
51 kZero_StencilOp, kZero_StencilOp,
52 kZero_StencilOp, kZero_StencilOp,
53 kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
54 0xffffffff, 0xffffffff,
55 0x0, 0x0,
56 0xffffffff, 0xffffffff
57};
58
59////// Winding
60
61// when we have separate stencil we increment front faces / decrement back faces
62// when we don't have wrap incr and decr we use the stencil test to simulate
63// them.
64
65static const GrStencilSettings gWindStencilSeparateWithWrap = {
66 kIncWrap_StencilOp, kDecWrap_StencilOp,
67 kKeep_StencilOp, kKeep_StencilOp,
68 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
69 0xffffffff, 0xffffffff,
70 0xffffffff, 0xffffffff,
71 0xffffffff, 0xffffffff
72};
73
74// if inc'ing the max value, invert to make 0
75// if dec'ing zero invert to make all ones.
76// we can't avoid touching the stencil on both passing and
77// failing, so we can't resctrict ourselves to the clip.
78static const GrStencilSettings gWindStencilSeparateNoWrap = {
79 kInvert_StencilOp, kInvert_StencilOp,
80 kIncClamp_StencilOp, kDecClamp_StencilOp,
81 kEqual_StencilFunc, kEqual_StencilFunc,
82 0xffffffff, 0xffffffff,
83 0xffffffff, 0x0,
84 0xffffffff, 0xffffffff
85};
86
87// When there are no separate faces we do two passes to setup the winding rule
88// stencil. First we draw the front faces and inc, then we draw the back faces
89// and dec. These are same as the above two split into the incrementing and
90// decrementing passes.
91static const GrStencilSettings gWindSingleStencilWithWrapInc = {
92 kIncWrap_StencilOp, kIncWrap_StencilOp,
93 kKeep_StencilOp, kKeep_StencilOp,
94 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
95 0xffffffff, 0xffffffff,
96 0xffffffff, 0xffffffff,
97 0xffffffff, 0xffffffff
98};
99static const GrStencilSettings gWindSingleStencilWithWrapDec = {
100 kDecWrap_StencilOp, kDecWrap_StencilOp,
101 kKeep_StencilOp, kKeep_StencilOp,
102 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
103 0xffffffff, 0xffffffff,
104 0xffffffff, 0xffffffff,
105 0xffffffff, 0xffffffff
106};
107static const GrStencilSettings gWindSingleStencilNoWrapInc = {
108 kInvert_StencilOp, kInvert_StencilOp,
109 kIncClamp_StencilOp, kIncClamp_StencilOp,
110 kEqual_StencilFunc, kEqual_StencilFunc,
111 0xffffffff, 0xffffffff,
112 0xffffffff, 0xffffffff,
113 0xffffffff, 0xffffffff
114};
115static const GrStencilSettings gWindSingleStencilNoWrapDec = {
116 kInvert_StencilOp, kInvert_StencilOp,
117 kDecClamp_StencilOp, kDecClamp_StencilOp,
118 kEqual_StencilFunc, kEqual_StencilFunc,
119 0xffffffff, 0xffffffff,
120 0x0, 0x0,
121 0xffffffff, 0xffffffff
122};
123
124static const GrStencilSettings gWindColorPass = {
125 kZero_StencilOp, kZero_StencilOp,
126 kZero_StencilOp, kZero_StencilOp,
127 kNonZeroIfInClip_StencilFunc, kNonZeroIfInClip_StencilFunc,
128 0xffffffff, 0xffffffff,
129 0x0, 0x0,
130 0xffffffff, 0xffffffff
131};
132
133static const GrStencilSettings gInvWindColorPass = {
134 kZero_StencilOp, kZero_StencilOp,
135 kZero_StencilOp, kZero_StencilOp,
136 kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
137 0xffffffff, 0xffffffff,
138 0x0, 0x0,
139 0xffffffff, 0xffffffff
140};
141
142////// Normal render to stencil
143
144// Sometimes the default path renderer can draw a path directly to the stencil
145// buffer without having to first resolve the interior / exterior.
146static const GrStencilSettings gDirectToStencil = {
147 kZero_StencilOp, kZero_StencilOp,
148 kIncClamp_StencilOp, kIncClamp_StencilOp,
149 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
150 0xffffffff, 0xffffffff,
151 0x0, 0x0,
152 0xffffffff, 0xffffffff
153};
154
155////////////////////////////////////////////////////////////////////////////////
156// Helpers for drawPath
bsalomon@google.comffca4002011-02-22 20:34:01 +0000157
reed@google.com07f3ee12011-05-16 17:21:57 +0000158static GrConvexHint getConvexHint(const SkPath& path) {
159 return path.isConvex() ? kConvex_ConvexHint : kConcave_ConvexHint;
160}
161
bsalomon@google.comffca4002011-02-22 20:34:01 +0000162#define STENCIL_OFF 0 // Always disable stencil (even when needed)
bsalomon@google.comffca4002011-02-22 20:34:01 +0000163
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000164static inline bool single_pass_path(const GrDrawTarget& target,
reed@google.com07f3ee12011-05-16 17:21:57 +0000165 const GrPath& path,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000166 GrPathFill fill) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000167#if STENCIL_OFF
168 return true;
169#else
170 if (kEvenOdd_PathFill == fill) {
reed@google.com07f3ee12011-05-16 17:21:57 +0000171 GrConvexHint hint = getConvexHint(path);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000172 return hint == kConvex_ConvexHint ||
173 hint == kNonOverlappingConvexPieces_ConvexHint;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000174 } else if (kWinding_PathFill == fill) {
reed@google.com07f3ee12011-05-16 17:21:57 +0000175 GrConvexHint hint = getConvexHint(path);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000176 return hint == kConvex_ConvexHint ||
177 hint == kNonOverlappingConvexPieces_ConvexHint ||
178 (hint == kSameWindingConvexPieces_ConvexHint &&
bsalomon@google.comffca4002011-02-22 20:34:01 +0000179 target.canDisableBlend() && !target.isDitherState());
180
181 }
182 return false;
183#endif
184}
185
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000186bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
reed@google.com07f3ee12011-05-16 17:21:57 +0000187 const GrPath& path,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000188 GrPathFill fill) const {
reed@google.com07f3ee12011-05-16 17:21:57 +0000189 return !single_pass_path(*target, path, fill);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000190}
191
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000192void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
193 GrDrawTarget::StageBitfield stages,
reed@google.com07f3ee12011-05-16 17:21:57 +0000194 const GrPath& path,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000195 GrPathFill fill,
196 const GrPoint* translate,
197 bool stencilOnly) {
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000198 SK_TRACE_EVENT1("GrDefaultPathRenderer::onDrawPath",
199 "points", SkStringPrintf("%i", path.countPoints()).c_str());
bsalomon@google.comffca4002011-02-22 20:34:01 +0000200
201 GrDrawTarget::AutoStateRestore asr(target);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000202 bool colorWritesWereDisabled = target->isColorWriteDisabled();
203 // face culling doesn't make sense here
204 GrAssert(GrDrawTarget::kBoth_DrawFace == target->getDrawFace());
bsalomon@google.comffca4002011-02-22 20:34:01 +0000205
206 GrMatrix viewM = target->getViewMatrix();
207 // In order to tesselate the path we get a bound on how much the matrix can
208 // stretch when mapping to screen coordinates.
209 GrScalar stretch = viewM.getMaxStretch();
210 bool useStretch = stretch > 0;
tomhudson@google.comd22b6e42011-06-24 15:53:40 +0000211 GrScalar tol = fCurveTolerance;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000212
213 if (!useStretch) {
214 // TODO: deal with perspective in some better way.
215 tol /= 10;
216 } else {
bungeman@google.com8c5753e2011-05-20 19:11:50 +0000217 tol = GrScalarDiv(tol, stretch);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000218 }
219 GrScalar tolSqd = GrMul(tol, tol);
220
221 int subpathCnt;
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000222 int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000223
224 GrVertexLayout layout = 0;
225 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
226 if ((1 << s) & stages) {
227 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
228 }
229 }
230
231 // add 4 to hold the bounding rect
232 GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxPts + 4, 0);
233
234 GrPoint* base = (GrPoint*) arg.vertices();
235 GrPoint* vert = base;
236 GrPoint* subpathBase = base;
237
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000238 SkAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000239
bsalomon@google.comffca4002011-02-22 20:34:01 +0000240 // TODO: use primitve restart if available rather than multiple draws
241 GrPrimitiveType type;
242 int passCount = 0;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000243 const GrStencilSettings* passes[3];
244 GrDrawTarget::DrawFace drawFace[3];
bsalomon@google.comffca4002011-02-22 20:34:01 +0000245 bool reverse = false;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000246 bool lastPassIsBounds;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000247
248 if (kHairLine_PathFill == fill) {
249 type = kLineStrip_PrimitiveType;
250 passCount = 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000251 if (stencilOnly) {
252 passes[0] = &gDirectToStencil;
253 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000254 passes[0] = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000255 }
256 lastPassIsBounds = false;
257 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000258 } else {
259 type = kTriangleFan_PrimitiveType;
reed@google.com07f3ee12011-05-16 17:21:57 +0000260 if (single_pass_path(*target, path, fill)) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000261 passCount = 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000262 if (stencilOnly) {
263 passes[0] = &gDirectToStencil;
264 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000265 passes[0] = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000266 }
267 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
268 lastPassIsBounds = false;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000269 } else {
270 switch (fill) {
271 case kInverseEvenOdd_PathFill:
272 reverse = true;
273 // fallthrough
274 case kEvenOdd_PathFill:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000275 passes[0] = &gEOStencilPass;
276 if (stencilOnly) {
277 passCount = 1;
278 lastPassIsBounds = false;
279 } else {
280 passCount = 2;
281 lastPassIsBounds = true;
282 if (reverse) {
283 passes[1] = &gInvEOColorPass;
284 } else {
285 passes[1] = &gEOColorPass;
286 }
287 }
288 drawFace[0] = drawFace[1] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000289 break;
290
291 case kInverseWinding_PathFill:
292 reverse = true;
293 // fallthrough
294 case kWinding_PathFill:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000295 if (fSeparateStencil) {
296 if (fStencilWrapOps) {
297 passes[0] = &gWindStencilSeparateWithWrap;
298 } else {
299 passes[0] = &gWindStencilSeparateNoWrap;
300 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000301 passCount = 2;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000302 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000303 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000304 if (fStencilWrapOps) {
305 passes[0] = &gWindSingleStencilWithWrapInc;
306 passes[1] = &gWindSingleStencilWithWrapDec;
307 } else {
308 passes[0] = &gWindSingleStencilNoWrapInc;
309 passes[1] = &gWindSingleStencilNoWrapDec;
310 }
311 // which is cw and which is ccw is arbitrary.
312 drawFace[0] = GrDrawTarget::kCW_DrawFace;
313 drawFace[1] = GrDrawTarget::kCCW_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000314 passCount = 3;
315 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000316 if (stencilOnly) {
317 lastPassIsBounds = false;
318 --passCount;
319 } else {
320 lastPassIsBounds = true;
321 drawFace[passCount-1] = GrDrawTarget::kBoth_DrawFace;
322 if (reverse) {
323 passes[passCount-1] = &gInvWindColorPass;
324 } else {
325 passes[passCount-1] = &gWindColorPass;
326 }
327 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000328 break;
329 default:
330 GrAssert(!"Unknown path fill!");
331 return;
332 }
333 }
334 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000335
336 GrPoint pts[4];
337
338 bool first = true;
339 int subpath = 0;
340
reed@google.com07f3ee12011-05-16 17:21:57 +0000341 SkPath::Iter iter(path, false);
342
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000343 {
344 SK_TRACE_EVENT0("GrDefaultPathRenderer::onDrawPath::assembleVerts");
bsalomon@google.comffca4002011-02-22 20:34:01 +0000345 for (;;) {
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000346
reed@google.com07f3ee12011-05-16 17:21:57 +0000347 GrPathCmd cmd = (GrPathCmd)iter.next(pts);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000348 switch (cmd) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000349 case kMove_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000350 if (!first) {
351 subpathVertCount[subpath] = vert-subpathBase;
352 subpathBase = vert;
353 ++subpath;
354 }
355 *vert = pts[0];
356 vert++;
357 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000358 case kLine_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000359 *vert = pts[1];
360 vert++;
361 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000362 case kQuadratic_PathCmd: {
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000363 GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2],
364 tolSqd, &vert,
365 GrPathUtils::quadraticPointCount(pts, tol));
bsalomon@google.comffca4002011-02-22 20:34:01 +0000366 break;
367 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000368 case kCubic_PathCmd: {
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000369 GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
370 tolSqd, &vert,
371 GrPathUtils::cubicPointCount(pts, tol));
bsalomon@google.comffca4002011-02-22 20:34:01 +0000372 break;
373 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000374 case kClose_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000375 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000376 case kEnd_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000377 subpathVertCount[subpath] = vert-subpathBase;
378 ++subpath; // this could be only in debug
379 goto FINISHED;
380 }
381 first = false;
382 }
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000383 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000384FINISHED:
385 GrAssert(subpath == subpathCnt);
386 GrAssert((vert - base) <= maxPts);
387
388 if (translate) {
389 int count = vert - base;
390 for (int i = 0; i < count; i++) {
391 base[i].offset(translate->fX, translate->fY);
392 }
393 }
394
bsalomon@google.comd302f142011-03-03 13:54:13 +0000395 // if we're stenciling we will follow with a pass that draws
396 // a bounding rect to set the color. We're stenciling when
397 // passCount > 1.
398 const int& boundVertexStart = maxPts;
399 GrPoint* boundsVerts = base + boundVertexStart;
400 if (lastPassIsBounds) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000401 GrRect bounds;
402 if (reverse) {
403 GrAssert(NULL != target->getRenderTarget());
404 // draw over the whole world.
405 bounds.setLTRB(0, 0,
406 GrIntToScalar(target->getRenderTarget()->width()),
407 GrIntToScalar(target->getRenderTarget()->height()));
408 GrMatrix vmi;
409 if (target->getViewInverse(&vmi)) {
410 vmi.mapRect(&bounds);
411 }
412 } else {
413 bounds.setBounds((GrPoint*)base, vert - base);
414 }
415 boundsVerts[0].setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight,
416 bounds.fBottom);
417 }
418
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000419 {
420 SK_TRACE_EVENT1("GrDefaultPathRenderer::onDrawPath::renderPasses",
421 "verts", SkStringPrintf("%i", vert - base).c_str());
bsalomon@google.comffca4002011-02-22 20:34:01 +0000422 for (int p = 0; p < passCount; ++p) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000423 target->setDrawFace(drawFace[p]);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000424 if (NULL != passes[p]) {
425 target->setStencil(*passes[p]);
426 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000427
428 if (lastPassIsBounds && (p == passCount-1)) {
429 if (!colorWritesWereDisabled) {
430 target->disableState(GrDrawTarget::kNoColorWrites_StateBit);
431 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000432 target->drawNonIndexed(kTriangleFan_PrimitiveType,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000433 boundVertexStart, 4);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000434
435 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000436 if (passCount > 1) {
437 target->enableState(GrDrawTarget::kNoColorWrites_StateBit);
438 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000439 int baseVertex = 0;
440 for (int sp = 0; sp < subpathCnt; ++sp) {
441 target->drawNonIndexed(type,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000442 baseVertex,
443 subpathVertCount[sp]);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000444 baseVertex += subpathVertCount[sp];
445 }
446 }
447 }
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000448 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000449}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000450
451void GrDefaultPathRenderer::drawPath(GrDrawTarget* target,
452 GrDrawTarget::StageBitfield stages,
reed@google.com07f3ee12011-05-16 17:21:57 +0000453 const GrPath& path,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000454 GrPathFill fill,
455 const GrPoint* translate) {
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000456 this->onDrawPath(target, stages, path, fill, translate, false);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000457}
458
459void GrDefaultPathRenderer::drawPathToStencil(GrDrawTarget* target,
reed@google.com07f3ee12011-05-16 17:21:57 +0000460 const GrPath& path,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000461 GrPathFill fill,
462 const GrPoint* translate) {
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000463 GrAssert(kInverseEvenOdd_PathFill != fill);
464 GrAssert(kInverseWinding_PathFill != fill);
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000465 this->onDrawPath(target, 0, path, fill, translate, true);
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000466}