gfx/skia/trunk/src/gpu/GrDefaultPathRenderer.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2011 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #include "GrDefaultPathRenderer.h"
michael@0 9
michael@0 10 #include "GrContext.h"
michael@0 11 #include "GrDrawState.h"
michael@0 12 #include "GrPathUtils.h"
michael@0 13 #include "SkString.h"
michael@0 14 #include "SkStrokeRec.h"
michael@0 15 #include "SkTLazy.h"
michael@0 16 #include "SkTrace.h"
michael@0 17
michael@0 18
michael@0 19 GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
michael@0 20 bool stencilWrapOpsSupport)
michael@0 21 : fSeparateStencil(separateStencilSupport)
michael@0 22 , fStencilWrapOps(stencilWrapOpsSupport) {
michael@0 23 }
michael@0 24
michael@0 25
michael@0 26 ////////////////////////////////////////////////////////////////////////////////
michael@0 27 // Stencil rules for paths
michael@0 28
michael@0 29 ////// Even/Odd
michael@0 30
michael@0 31 GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
michael@0 32 kInvert_StencilOp,
michael@0 33 kKeep_StencilOp,
michael@0 34 kAlwaysIfInClip_StencilFunc,
michael@0 35 0xffff,
michael@0 36 0xffff,
michael@0 37 0xffff);
michael@0 38
michael@0 39 // ok not to check clip b/c stencil pass only wrote inside clip
michael@0 40 GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
michael@0 41 kZero_StencilOp,
michael@0 42 kZero_StencilOp,
michael@0 43 kNotEqual_StencilFunc,
michael@0 44 0xffff,
michael@0 45 0x0000,
michael@0 46 0xffff);
michael@0 47
michael@0 48 // have to check clip b/c outside clip will always be zero.
michael@0 49 GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
michael@0 50 kZero_StencilOp,
michael@0 51 kZero_StencilOp,
michael@0 52 kEqualIfInClip_StencilFunc,
michael@0 53 0xffff,
michael@0 54 0x0000,
michael@0 55 0xffff);
michael@0 56
michael@0 57 ////// Winding
michael@0 58
michael@0 59 // when we have separate stencil we increment front faces / decrement back faces
michael@0 60 // when we don't have wrap incr and decr we use the stencil test to simulate
michael@0 61 // them.
michael@0 62
michael@0 63 GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
michael@0 64 kIncWrap_StencilOp, kDecWrap_StencilOp,
michael@0 65 kKeep_StencilOp, kKeep_StencilOp,
michael@0 66 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
michael@0 67 0xffff, 0xffff,
michael@0 68 0xffff, 0xffff,
michael@0 69 0xffff, 0xffff);
michael@0 70
michael@0 71 // if inc'ing the max value, invert to make 0
michael@0 72 // if dec'ing zero invert to make all ones.
michael@0 73 // we can't avoid touching the stencil on both passing and
michael@0 74 // failing, so we can't resctrict ourselves to the clip.
michael@0 75 GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
michael@0 76 kInvert_StencilOp, kInvert_StencilOp,
michael@0 77 kIncClamp_StencilOp, kDecClamp_StencilOp,
michael@0 78 kEqual_StencilFunc, kEqual_StencilFunc,
michael@0 79 0xffff, 0xffff,
michael@0 80 0xffff, 0x0000,
michael@0 81 0xffff, 0xffff);
michael@0 82
michael@0 83 // When there are no separate faces we do two passes to setup the winding rule
michael@0 84 // stencil. First we draw the front faces and inc, then we draw the back faces
michael@0 85 // and dec. These are same as the above two split into the incrementing and
michael@0 86 // decrementing passes.
michael@0 87 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
michael@0 88 kIncWrap_StencilOp,
michael@0 89 kKeep_StencilOp,
michael@0 90 kAlwaysIfInClip_StencilFunc,
michael@0 91 0xffff,
michael@0 92 0xffff,
michael@0 93 0xffff);
michael@0 94
michael@0 95 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
michael@0 96 kDecWrap_StencilOp,
michael@0 97 kKeep_StencilOp,
michael@0 98 kAlwaysIfInClip_StencilFunc,
michael@0 99 0xffff,
michael@0 100 0xffff,
michael@0 101 0xffff);
michael@0 102
michael@0 103 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
michael@0 104 kInvert_StencilOp,
michael@0 105 kIncClamp_StencilOp,
michael@0 106 kEqual_StencilFunc,
michael@0 107 0xffff,
michael@0 108 0xffff,
michael@0 109 0xffff);
michael@0 110
michael@0 111 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
michael@0 112 kInvert_StencilOp,
michael@0 113 kDecClamp_StencilOp,
michael@0 114 kEqual_StencilFunc,
michael@0 115 0xffff,
michael@0 116 0x0000,
michael@0 117 0xffff);
michael@0 118
michael@0 119 // Color passes are the same whether we use the two-sided stencil or two passes
michael@0 120
michael@0 121 GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
michael@0 122 kZero_StencilOp,
michael@0 123 kZero_StencilOp,
michael@0 124 kNonZeroIfInClip_StencilFunc,
michael@0 125 0xffff,
michael@0 126 0x0000,
michael@0 127 0xffff);
michael@0 128
michael@0 129 GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
michael@0 130 kZero_StencilOp,
michael@0 131 kZero_StencilOp,
michael@0 132 kEqualIfInClip_StencilFunc,
michael@0 133 0xffff,
michael@0 134 0x0000,
michael@0 135 0xffff);
michael@0 136
michael@0 137 ////// Normal render to stencil
michael@0 138
michael@0 139 // Sometimes the default path renderer can draw a path directly to the stencil
michael@0 140 // buffer without having to first resolve the interior / exterior.
michael@0 141 GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
michael@0 142 kZero_StencilOp,
michael@0 143 kIncClamp_StencilOp,
michael@0 144 kAlwaysIfInClip_StencilFunc,
michael@0 145 0xffff,
michael@0 146 0x0000,
michael@0 147 0xffff);
michael@0 148
michael@0 149 ////////////////////////////////////////////////////////////////////////////////
michael@0 150 // Helpers for drawPath
michael@0 151
michael@0 152 #define STENCIL_OFF 0 // Always disable stencil (even when needed)
michael@0 153
michael@0 154 static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& stroke) {
michael@0 155 #if STENCIL_OFF
michael@0 156 return true;
michael@0 157 #else
michael@0 158 if (!stroke.isHairlineStyle() && !path.isInverseFillType()) {
michael@0 159 return path.isConvex();
michael@0 160 }
michael@0 161 return false;
michael@0 162 #endif
michael@0 163 }
michael@0 164
michael@0 165 GrPathRenderer::StencilSupport GrDefaultPathRenderer::onGetStencilSupport(
michael@0 166 const SkPath& path,
michael@0 167 const SkStrokeRec& stroke,
michael@0 168 const GrDrawTarget*) const {
michael@0 169 if (single_pass_path(path, stroke)) {
michael@0 170 return GrPathRenderer::kNoRestriction_StencilSupport;
michael@0 171 } else {
michael@0 172 return GrPathRenderer::kStencilOnly_StencilSupport;
michael@0 173 }
michael@0 174 }
michael@0 175
michael@0 176 static inline void append_countour_edge_indices(bool hairLine,
michael@0 177 uint16_t fanCenterIdx,
michael@0 178 uint16_t edgeV0Idx,
michael@0 179 uint16_t** indices) {
michael@0 180 // when drawing lines we're appending line segments along
michael@0 181 // the contour. When applying the other fill rules we're
michael@0 182 // drawing triangle fans around fanCenterIdx.
michael@0 183 if (!hairLine) {
michael@0 184 *((*indices)++) = fanCenterIdx;
michael@0 185 }
michael@0 186 *((*indices)++) = edgeV0Idx;
michael@0 187 *((*indices)++) = edgeV0Idx + 1;
michael@0 188 }
michael@0 189
michael@0 190 bool GrDefaultPathRenderer::createGeom(const SkPath& path,
michael@0 191 const SkStrokeRec& stroke,
michael@0 192 SkScalar srcSpaceTol,
michael@0 193 GrDrawTarget* target,
michael@0 194 GrPrimitiveType* primType,
michael@0 195 int* vertexCnt,
michael@0 196 int* indexCnt,
michael@0 197 GrDrawTarget::AutoReleaseGeometry* arg) {
michael@0 198 {
michael@0 199 SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
michael@0 200
michael@0 201 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol);
michael@0 202 int contourCnt;
michael@0 203 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt,
michael@0 204 srcSpaceTol);
michael@0 205
michael@0 206 if (maxPts <= 0) {
michael@0 207 return false;
michael@0 208 }
michael@0 209 if (maxPts > ((int)SK_MaxU16 + 1)) {
michael@0 210 GrPrintf("Path not rendered, too many verts (%d)\n", maxPts);
michael@0 211 return false;
michael@0 212 }
michael@0 213
michael@0 214 bool indexed = contourCnt > 1;
michael@0 215
michael@0 216 const bool isHairline = stroke.isHairlineStyle();
michael@0 217
michael@0 218 int maxIdxs = 0;
michael@0 219 if (isHairline) {
michael@0 220 if (indexed) {
michael@0 221 maxIdxs = 2 * maxPts;
michael@0 222 *primType = kLines_GrPrimitiveType;
michael@0 223 } else {
michael@0 224 *primType = kLineStrip_GrPrimitiveType;
michael@0 225 }
michael@0 226 } else {
michael@0 227 if (indexed) {
michael@0 228 maxIdxs = 3 * maxPts;
michael@0 229 *primType = kTriangles_GrPrimitiveType;
michael@0 230 } else {
michael@0 231 *primType = kTriangleFan_GrPrimitiveType;
michael@0 232 }
michael@0 233 }
michael@0 234
michael@0 235 target->drawState()->setDefaultVertexAttribs();
michael@0 236 if (!arg->set(target, maxPts, maxIdxs)) {
michael@0 237 return false;
michael@0 238 }
michael@0 239
michael@0 240 uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices());
michael@0 241 uint16_t* idx = idxBase;
michael@0 242 uint16_t subpathIdxStart = 0;
michael@0 243
michael@0 244 GrPoint* base = reinterpret_cast<GrPoint*>(arg->vertices());
michael@0 245 SkASSERT(NULL != base);
michael@0 246 GrPoint* vert = base;
michael@0 247
michael@0 248 GrPoint pts[4];
michael@0 249
michael@0 250 bool first = true;
michael@0 251 int subpath = 0;
michael@0 252
michael@0 253 SkPath::Iter iter(path, false);
michael@0 254
michael@0 255 for (;;) {
michael@0 256 SkPath::Verb verb = iter.next(pts);
michael@0 257 switch (verb) {
michael@0 258 case SkPath::kConic_Verb:
michael@0 259 SkASSERT(0);
michael@0 260 break;
michael@0 261 case SkPath::kMove_Verb:
michael@0 262 if (!first) {
michael@0 263 uint16_t currIdx = (uint16_t) (vert - base);
michael@0 264 subpathIdxStart = currIdx;
michael@0 265 ++subpath;
michael@0 266 }
michael@0 267 *vert = pts[0];
michael@0 268 vert++;
michael@0 269 break;
michael@0 270 case SkPath::kLine_Verb:
michael@0 271 if (indexed) {
michael@0 272 uint16_t prevIdx = (uint16_t)(vert - base) - 1;
michael@0 273 append_countour_edge_indices(isHairline, subpathIdxStart,
michael@0 274 prevIdx, &idx);
michael@0 275 }
michael@0 276 *(vert++) = pts[1];
michael@0 277 break;
michael@0 278 case SkPath::kQuad_Verb: {
michael@0 279 // first pt of quad is the pt we ended on in previous step
michael@0 280 uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1;
michael@0 281 uint16_t numPts = (uint16_t)
michael@0 282 GrPathUtils::generateQuadraticPoints(
michael@0 283 pts[0], pts[1], pts[2],
michael@0 284 srcSpaceTolSqd, &vert,
michael@0 285 GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
michael@0 286 if (indexed) {
michael@0 287 for (uint16_t i = 0; i < numPts; ++i) {
michael@0 288 append_countour_edge_indices(isHairline, subpathIdxStart,
michael@0 289 firstQPtIdx + i, &idx);
michael@0 290 }
michael@0 291 }
michael@0 292 break;
michael@0 293 }
michael@0 294 case SkPath::kCubic_Verb: {
michael@0 295 // first pt of cubic is the pt we ended on in previous step
michael@0 296 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1;
michael@0 297 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
michael@0 298 pts[0], pts[1], pts[2], pts[3],
michael@0 299 srcSpaceTolSqd, &vert,
michael@0 300 GrPathUtils::cubicPointCount(pts, srcSpaceTol));
michael@0 301 if (indexed) {
michael@0 302 for (uint16_t i = 0; i < numPts; ++i) {
michael@0 303 append_countour_edge_indices(isHairline, subpathIdxStart,
michael@0 304 firstCPtIdx + i, &idx);
michael@0 305 }
michael@0 306 }
michael@0 307 break;
michael@0 308 }
michael@0 309 case SkPath::kClose_Verb:
michael@0 310 break;
michael@0 311 case SkPath::kDone_Verb:
michael@0 312 // uint16_t currIdx = (uint16_t) (vert - base);
michael@0 313 goto FINISHED;
michael@0 314 }
michael@0 315 first = false;
michael@0 316 }
michael@0 317 FINISHED:
michael@0 318 SkASSERT((vert - base) <= maxPts);
michael@0 319 SkASSERT((idx - idxBase) <= maxIdxs);
michael@0 320
michael@0 321 *vertexCnt = static_cast<int>(vert - base);
michael@0 322 *indexCnt = static_cast<int>(idx - idxBase);
michael@0 323
michael@0 324 }
michael@0 325 return true;
michael@0 326 }
michael@0 327
michael@0 328 bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
michael@0 329 const SkStrokeRec& origStroke,
michael@0 330 GrDrawTarget* target,
michael@0 331 bool stencilOnly) {
michael@0 332
michael@0 333 SkMatrix viewM = target->getDrawState().getViewMatrix();
michael@0 334 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
michael@0 335
michael@0 336 SkScalar hairlineCoverage;
michael@0 337 if (IsStrokeHairlineOrEquivalent(*stroke, target->getDrawState().getViewMatrix(),
michael@0 338 &hairlineCoverage)) {
michael@0 339 uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage *
michael@0 340 target->getDrawState().getCoverage());
michael@0 341 target->drawState()->setCoverage(newCoverage);
michael@0 342
michael@0 343 if (!stroke->isHairlineStyle()) {
michael@0 344 stroke.writable()->setHairlineStyle();
michael@0 345 }
michael@0 346 }
michael@0 347
michael@0 348 SkScalar tol = SK_Scalar1;
michael@0 349 tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds());
michael@0 350
michael@0 351 int vertexCnt;
michael@0 352 int indexCnt;
michael@0 353 GrPrimitiveType primType;
michael@0 354 GrDrawTarget::AutoReleaseGeometry arg;
michael@0 355 if (!this->createGeom(path,
michael@0 356 *stroke,
michael@0 357 tol,
michael@0 358 target,
michael@0 359 &primType,
michael@0 360 &vertexCnt,
michael@0 361 &indexCnt,
michael@0 362 &arg)) {
michael@0 363 return false;
michael@0 364 }
michael@0 365
michael@0 366 SkASSERT(NULL != target);
michael@0 367 GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
michael@0 368 GrDrawState* drawState = target->drawState();
michael@0 369 bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
michael@0 370 // face culling doesn't make sense here
michael@0 371 SkASSERT(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
michael@0 372
michael@0 373 int passCount = 0;
michael@0 374 const GrStencilSettings* passes[3];
michael@0 375 GrDrawState::DrawFace drawFace[3];
michael@0 376 bool reverse = false;
michael@0 377 bool lastPassIsBounds;
michael@0 378
michael@0 379 if (stroke->isHairlineStyle()) {
michael@0 380 passCount = 1;
michael@0 381 if (stencilOnly) {
michael@0 382 passes[0] = &gDirectToStencil;
michael@0 383 } else {
michael@0 384 passes[0] = NULL;
michael@0 385 }
michael@0 386 lastPassIsBounds = false;
michael@0 387 drawFace[0] = GrDrawState::kBoth_DrawFace;
michael@0 388 } else {
michael@0 389 if (single_pass_path(path, *stroke)) {
michael@0 390 passCount = 1;
michael@0 391 if (stencilOnly) {
michael@0 392 passes[0] = &gDirectToStencil;
michael@0 393 } else {
michael@0 394 passes[0] = NULL;
michael@0 395 }
michael@0 396 drawFace[0] = GrDrawState::kBoth_DrawFace;
michael@0 397 lastPassIsBounds = false;
michael@0 398 } else {
michael@0 399 switch (path.getFillType()) {
michael@0 400 case SkPath::kInverseEvenOdd_FillType:
michael@0 401 reverse = true;
michael@0 402 // fallthrough
michael@0 403 case SkPath::kEvenOdd_FillType:
michael@0 404 passes[0] = &gEOStencilPass;
michael@0 405 if (stencilOnly) {
michael@0 406 passCount = 1;
michael@0 407 lastPassIsBounds = false;
michael@0 408 } else {
michael@0 409 passCount = 2;
michael@0 410 lastPassIsBounds = true;
michael@0 411 if (reverse) {
michael@0 412 passes[1] = &gInvEOColorPass;
michael@0 413 } else {
michael@0 414 passes[1] = &gEOColorPass;
michael@0 415 }
michael@0 416 }
michael@0 417 drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
michael@0 418 break;
michael@0 419
michael@0 420 case SkPath::kInverseWinding_FillType:
michael@0 421 reverse = true;
michael@0 422 // fallthrough
michael@0 423 case SkPath::kWinding_FillType:
michael@0 424 if (fSeparateStencil) {
michael@0 425 if (fStencilWrapOps) {
michael@0 426 passes[0] = &gWindStencilSeparateWithWrap;
michael@0 427 } else {
michael@0 428 passes[0] = &gWindStencilSeparateNoWrap;
michael@0 429 }
michael@0 430 passCount = 2;
michael@0 431 drawFace[0] = GrDrawState::kBoth_DrawFace;
michael@0 432 } else {
michael@0 433 if (fStencilWrapOps) {
michael@0 434 passes[0] = &gWindSingleStencilWithWrapInc;
michael@0 435 passes[1] = &gWindSingleStencilWithWrapDec;
michael@0 436 } else {
michael@0 437 passes[0] = &gWindSingleStencilNoWrapInc;
michael@0 438 passes[1] = &gWindSingleStencilNoWrapDec;
michael@0 439 }
michael@0 440 // which is cw and which is ccw is arbitrary.
michael@0 441 drawFace[0] = GrDrawState::kCW_DrawFace;
michael@0 442 drawFace[1] = GrDrawState::kCCW_DrawFace;
michael@0 443 passCount = 3;
michael@0 444 }
michael@0 445 if (stencilOnly) {
michael@0 446 lastPassIsBounds = false;
michael@0 447 --passCount;
michael@0 448 } else {
michael@0 449 lastPassIsBounds = true;
michael@0 450 drawFace[passCount-1] = GrDrawState::kBoth_DrawFace;
michael@0 451 if (reverse) {
michael@0 452 passes[passCount-1] = &gInvWindColorPass;
michael@0 453 } else {
michael@0 454 passes[passCount-1] = &gWindColorPass;
michael@0 455 }
michael@0 456 }
michael@0 457 break;
michael@0 458 default:
michael@0 459 SkDEBUGFAIL("Unknown path fFill!");
michael@0 460 return false;
michael@0 461 }
michael@0 462 }
michael@0 463 }
michael@0 464
michael@0 465 SkRect devBounds;
michael@0 466 GetPathDevBounds(path, drawState->getRenderTarget(), viewM, &devBounds);
michael@0 467
michael@0 468 for (int p = 0; p < passCount; ++p) {
michael@0 469 drawState->setDrawFace(drawFace[p]);
michael@0 470 if (NULL != passes[p]) {
michael@0 471 *drawState->stencil() = *passes[p];
michael@0 472 }
michael@0 473
michael@0 474 if (lastPassIsBounds && (p == passCount-1)) {
michael@0 475 if (!colorWritesWereDisabled) {
michael@0 476 drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
michael@0 477 }
michael@0 478 SkRect bounds;
michael@0 479 GrDrawState::AutoViewMatrixRestore avmr;
michael@0 480 if (reverse) {
michael@0 481 SkASSERT(NULL != drawState->getRenderTarget());
michael@0 482 // draw over the dev bounds (which will be the whole dst surface for inv fill).
michael@0 483 bounds = devBounds;
michael@0 484 SkMatrix vmi;
michael@0 485 // mapRect through persp matrix may not be correct
michael@0 486 if (!drawState->getViewMatrix().hasPerspective() &&
michael@0 487 drawState->getViewInverse(&vmi)) {
michael@0 488 vmi.mapRect(&bounds);
michael@0 489 } else {
michael@0 490 avmr.setIdentity(drawState);
michael@0 491 }
michael@0 492 } else {
michael@0 493 bounds = path.getBounds();
michael@0 494 }
michael@0 495 GrDrawTarget::AutoGeometryAndStatePush agasp(target, GrDrawTarget::kPreserve_ASRInit);
michael@0 496 target->drawSimpleRect(bounds, NULL);
michael@0 497 } else {
michael@0 498 if (passCount > 1) {
michael@0 499 drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
michael@0 500 }
michael@0 501 if (indexCnt) {
michael@0 502 target->drawIndexed(primType, 0, 0,
michael@0 503 vertexCnt, indexCnt, &devBounds);
michael@0 504 } else {
michael@0 505 target->drawNonIndexed(primType, 0, vertexCnt, &devBounds);
michael@0 506 }
michael@0 507 }
michael@0 508 }
michael@0 509 return true;
michael@0 510 }
michael@0 511
michael@0 512 bool GrDefaultPathRenderer::canDrawPath(const SkPath& path,
michael@0 513 const SkStrokeRec& stroke,
michael@0 514 const GrDrawTarget* target,
michael@0 515 bool antiAlias) const {
michael@0 516 // this class can draw any path with any fill but doesn't do any anti-aliasing.
michael@0 517
michael@0 518 return !antiAlias &&
michael@0 519 (stroke.isFillStyle() ||
michael@0 520 IsStrokeHairlineOrEquivalent(stroke, target->getDrawState().getViewMatrix(), NULL));
michael@0 521 }
michael@0 522
michael@0 523 bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
michael@0 524 const SkStrokeRec& stroke,
michael@0 525 GrDrawTarget* target,
michael@0 526 bool antiAlias) {
michael@0 527 return this->internalDrawPath(path,
michael@0 528 stroke,
michael@0 529 target,
michael@0 530 false);
michael@0 531 }
michael@0 532
michael@0 533 void GrDefaultPathRenderer::onStencilPath(const SkPath& path,
michael@0 534 const SkStrokeRec& stroke,
michael@0 535 GrDrawTarget* target) {
michael@0 536 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType());
michael@0 537 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType());
michael@0 538 this->internalDrawPath(path, stroke, target, true);
michael@0 539 }

mercurial