本文整理汇总了C++中SkPath::getFillType方法的典型用法代码示例。如果您正苦于以下问题:C++ SkPath::getFillType方法的具体用法?C++ SkPath::getFillType怎么用?C++ SkPath::getFillType使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SkPath
的用法示例。
在下文中一共展示了SkPath::getFillType方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: innerPathOp
static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
const SkPathOp shapeOp, const char* testName, bool expectSuccess) {
#if 0 && DEBUG_SHOW_TEST_NAME
showName(a, b, shapeOp);
#endif
SkPath out;
if (!OpDebug(a, b, shapeOp, &out, expectSuccess SkDEBUGPARAMS(testName))) {
SkDebugf("%s did not expect failure\n", __FUNCTION__);
REPORTER_ASSERT(reporter, 0);
return false;
}
if (!reporter->verbose()) {
return true;
}
SkPath pathOut, scaledPathOut;
SkRegion rgnA, rgnB, openClip, rgnOut;
openClip.setRect(-16000, -16000, 16000, 16000);
rgnA.setPath(a, openClip);
rgnB.setPath(b, openClip);
rgnOut.op(rgnA, rgnB, (SkRegion::Op) shapeOp);
rgnOut.getBoundaryPath(&pathOut);
SkMatrix scale;
scaleMatrix(a, b, scale);
SkRegion scaledRgnA, scaledRgnB, scaledRgnOut;
SkPath scaledA, scaledB;
scaledA.addPath(a, scale);
scaledA.setFillType(a.getFillType());
scaledB.addPath(b, scale);
scaledB.setFillType(b.getFillType());
scaledRgnA.setPath(scaledA, openClip);
scaledRgnB.setPath(scaledB, openClip);
scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) shapeOp);
scaledRgnOut.getBoundaryPath(&scaledPathOut);
SkBitmap bitmap;
SkPath scaledOut;
scaledOut.addPath(out, scale);
scaledOut.setFillType(out.getFillType());
int result = comparePaths(reporter, testName, pathOut, scaledPathOut, out, scaledOut, bitmap,
a, b, shapeOp, scale, expectSuccess);
reporter->bumpTestCount();
return result == 0;
}
示例2: SkHitTestPathEx
bool SkHitTestPathEx(const SkPath& path, SkScalar x, SkScalar y) {
bool isInverse = path.isInverseFillType();
if (path.isEmpty()) {
return isInverse;
}
const SkRect& bounds = path.getBounds();
if (!bounds.contains(x, y)) {
return isInverse;
}
SkPath::Iter iter(path, true);
bool done = false;
int w = 0;
do {
SkPoint pts[4];
switch (iter.next(pts, false)) {
case SkPath::kMove_Verb:
case SkPath::kClose_Verb:
break;
case SkPath::kLine_Verb:
w += winding_line(pts, x, y);
break;
case SkPath::kQuad_Verb:
w += winding_quad(pts, x, y);
break;
case SkPath::kCubic_Verb:
w += winding_cubic(pts, x, y);
break;
case SkPath::kDone_Verb:
done = true;
break;
}
} while (!done);
switch (path.getFillType()) {
case SkPath::kEvenOdd_FillType:
case SkPath::kInverseEvenOdd_FillType:
w &= 1;
break;
default:
break;
}
return SkToBool(w);
}
示例3: drawAndTest
static void drawAndTest(skiatest::Reporter* reporter, const SkPath& path,
const SkPaint& paint, bool shouldDraw) {
SkBitmap bm;
bm.allocN32Pixels(DIMENSION, DIMENSION);
SkASSERT(DIMENSION*4 == bm.rowBytes()); // ensure no padding on each row
bm.eraseColor(SK_ColorTRANSPARENT);
SkCanvas canvas(bm);
SkPaint p(paint);
p.setColor(SK_ColorWHITE);
canvas.drawPath(path, p);
size_t count = DIMENSION * DIMENSION;
const SkPMColor* ptr = bm.getAddr32(0, 0);
SkPMColor andValue = ~0U;
SkPMColor orValue = 0;
for (size_t i = 0; i < count; ++i) {
SkPMColor c = ptr[i];
andValue &= c;
orValue |= c;
}
// success means we drew everywhere or nowhere (depending on shouldDraw)
bool success = shouldDraw ? (~0U == andValue) : (0 == orValue);
if (!success) {
const char* str;
if (shouldDraw) {
str = "Path expected to draw everywhere, but didn't. ";
} else {
str = "Path expected to draw nowhere, but did. ";
}
ERRORF(reporter, "%s style[%d] cap[%d] join[%d] antialias[%d]"
" filltype[%d] ptcount[%d]", str, paint.getStyle(),
paint.getStrokeCap(), paint.getStrokeJoin(),
paint.isAntiAlias(), path.getFillType(), path.countPoints());
// uncomment this if you want to step in to see the failure
// canvas.drawPath(path, p);
}
}
示例4: drawPath
void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& path,
const SkPaint& paint, const SkMatrix* prePathMatrix,
bool pathIsMutable) {
NOT_IMPLEMENTED(prePathMatrix != NULL, true);
if (paint.getPathEffect()) {
// Apply the path effect to path and draw it that way.
SkPath noEffectPath;
paint.getFillPath(path, &noEffectPath);
SkPaint noEffectPaint(paint);
SkSafeUnref(noEffectPaint.setPathEffect(NULL));
drawPath(d, noEffectPath, noEffectPaint, NULL, true);
return;
}
updateGSFromPaint(paint, false);
SkPDFUtils::EmitPath(path, &fContent);
SkPDFUtils::PaintPath(paint.getStyle(), path.getFillType(), &fContent);
}
示例5: addPathData
void SkDebugCanvas::addPathData(const SkPath& path, const char* pathName) {
SkPath::RawIter iter(path);
SkPath::FillType fillType = path.getFillType();
fClipStackData.appendf("%sSkPath %s;<br>", kHTML4SpaceIndent, pathName);
fClipStackData.appendf("%s%s.setFillType(SkPath::%s);<br>", kHTML4SpaceIndent, pathName,
gFillTypeStrs[fillType]);
iter.setPath(path);
uint8_t verb;
SkPoint pts[4];
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
switch (verb) {
case SkPath::kMove_Verb:
fClipStackData.appendf("%s%s.moveTo(", kHTML4SpaceIndent, pathName);
this->outputPoints(&pts[0], 1);
continue;
case SkPath::kLine_Verb:
fClipStackData.appendf("%s%s.lineTo(", kHTML4SpaceIndent, pathName);
this->outputPoints(&pts[1], 1);
break;
case SkPath::kQuad_Verb:
fClipStackData.appendf("%s%s.quadTo(", kHTML4SpaceIndent, pathName);
this->outputPoints(&pts[1], 2);
break;
case SkPath::kConic_Verb:
fClipStackData.appendf("%s%s.conicTo(", kHTML4SpaceIndent, pathName);
this->outputConicPoints(&pts[1], iter.conicWeight());
break;
case SkPath::kCubic_Verb:
fClipStackData.appendf("%s%s.cubicTo(", kHTML4SpaceIndent, pathName);
this->outputPoints(&pts[1], 3);
break;
case SkPath::kClose_Verb:
fClipStackData.appendf("%s%s.close();<br>", kHTML4SpaceIndent, pathName);
break;
default:
SkDEBUGFAIL("bad verb");
return;
}
}
}
示例6: iter
PassRefPtr<JSONObject> LoggingCanvas::objectForSkPath(const SkPath& path)
{
RefPtr<JSONObject> pathItem = JSONObject::create();
pathItem->setString("fillType", fillTypeName(path.getFillType()));
pathItem->setString("convexity", convexityName(path.getConvexity()));
pathItem->setBoolean("isRect", path.isRect(0));
SkPath::Iter iter(path, false);
SkPoint points[4];
RefPtr<JSONArray> pathPointsArray = JSONArray::create();
for (SkPath::Verb verb = iter.next(points, false); verb != SkPath::kDone_Verb; verb = iter.next(points, false)) {
VerbParams verbParams = segmentParams(verb);
RefPtr<JSONObject> pathPointItem = JSONObject::create();
pathPointItem->setString("verb", verbParams.name);
ASSERT(verbParams.pointCount + verbParams.pointOffset <= WTF_ARRAY_LENGTH(points));
pathPointItem->setArray("points", arrayForSkPoints(verbParams.pointCount, points + verbParams.pointOffset));
if (SkPath::kConic_Verb == verb)
pathPointItem->setNumber("conicWeight", iter.conicWeight());
pathPointsArray->pushObject(pathPointItem);
}
pathItem->setArray("pathPoints", pathPointsArray);
pathItem->setObject("bounds", objectForSkRect(path.getBounds()));
return pathItem.release();
}
示例7: internalDrawPath
bool GrDefaultPathRenderer::internalDrawPath(GrDrawContext* drawContext,
const GrPaint& paint,
const GrUserStencilSettings& userStencilSettings,
const GrClip& clip,
const SkMatrix& viewMatrix,
const GrShape& shape,
bool stencilOnly) {
SkPath path;
shape.asPath(&path);
SkScalar hairlineCoverage;
uint8_t newCoverage = 0xff;
bool isHairline = false;
if (IsStrokeHairlineOrEquivalent(shape.style(), viewMatrix, &hairlineCoverage)) {
newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
isHairline = true;
} else {
SkASSERT(shape.style().isSimpleFill());
}
int passCount = 0;
const GrUserStencilSettings* passes[3];
GrDrawFace drawFace[3];
bool reverse = false;
bool lastPassIsBounds;
if (isHairline) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
} else {
passes[0] = &userStencilSettings;
}
lastPassIsBounds = false;
drawFace[0] = GrDrawFace::kBoth;
} else {
if (single_pass_shape(shape)) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
} else {
passes[0] = &userStencilSettings;
}
drawFace[0] = GrDrawFace::kBoth;
lastPassIsBounds = false;
} else {
switch (path.getFillType()) {
case SkPath::kInverseEvenOdd_FillType:
reverse = true;
// fallthrough
case SkPath::kEvenOdd_FillType:
passes[0] = &gEOStencilPass;
if (stencilOnly) {
passCount = 1;
lastPassIsBounds = false;
} else {
passCount = 2;
lastPassIsBounds = true;
if (reverse) {
passes[1] = &gInvEOColorPass;
} else {
passes[1] = &gEOColorPass;
}
}
drawFace[0] = drawFace[1] = GrDrawFace::kBoth;
break;
case SkPath::kInverseWinding_FillType:
reverse = true;
// fallthrough
case SkPath::kWinding_FillType:
if (fSeparateStencil) {
if (fStencilWrapOps) {
passes[0] = &gWindStencilSeparateWithWrap;
} else {
passes[0] = &gWindStencilSeparateNoWrap;
}
passCount = 2;
drawFace[0] = GrDrawFace::kBoth;
} else {
if (fStencilWrapOps) {
passes[0] = &gWindSingleStencilWithWrapInc;
passes[1] = &gWindSingleStencilWithWrapDec;
} else {
passes[0] = &gWindSingleStencilNoWrapInc;
passes[1] = &gWindSingleStencilNoWrapDec;
}
// which is cw and which is ccw is arbitrary.
drawFace[0] = GrDrawFace::kCW;
drawFace[1] = GrDrawFace::kCCW;
passCount = 3;
}
if (stencilOnly) {
lastPassIsBounds = false;
--passCount;
} else {
lastPassIsBounds = true;
drawFace[passCount-1] = GrDrawFace::kBoth;
if (reverse) {
passes[passCount-1] = &gInvWindColorPass;
//.........这里部分代码省略.........
示例8: onDrawPath
bool GrStencilAndCoverPathRenderer::onDrawPath(GrDrawTarget* target,
GrPipelineBuilder* pipelineBuilder,
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
const GrStrokeInfo& stroke,
bool antiAlias) {
SkASSERT(!antiAlias);
SkASSERT(!stroke.getStrokeRec().isHairlineStyle());
SkASSERT(!stroke.isDashed());
SkASSERT(pipelineBuilder->getStencil().isDisabled());
SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke.getStrokeRec()));
if (path.isInverseFillType()) {
GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
kZero_StencilOp,
kZero_StencilOp,
// We know our rect will hit pixels outside the clip and the user bits will be 0
// outside the clip. So we can't just fill where the user bits are 0. We also need to
// check that the clip bit is set.
kEqualIfInClip_StencilFunc,
0xffff,
0x0000,
0xffff);
pipelineBuilder->setStencil(kInvertedStencilPass);
// fake inverse with a stencil and cover
SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(GrColor_WHITE, viewMatrix));
target->stencilPath(pipelineBuilder, pp, p, convert_skpath_filltype(path.getFillType()));
SkMatrix invert = SkMatrix::I();
SkRect bounds =
SkRect::MakeLTRB(0, 0, SkIntToScalar(pipelineBuilder->getRenderTarget()->width()),
SkIntToScalar(pipelineBuilder->getRenderTarget()->height()));
SkMatrix vmi;
// mapRect through persp matrix may not be correct
if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
vmi.mapRect(&bounds);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
SkScalar bloat = viewMatrix.getMaxScale() * SK_ScalarHalf;
bounds.outset(bloat, bloat);
} else {
if (!viewMatrix.invert(&invert)) {
return false;
}
}
const SkMatrix& viewM = viewMatrix.hasPerspective() ? SkMatrix::I() : viewMatrix;
target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &invert);
} else {
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
kZero_StencilOp,
kZero_StencilOp,
kNotEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
pipelineBuilder->setStencil(kStencilPass);
SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(color, viewMatrix));
target->drawPath(pipelineBuilder, pp, p, convert_skpath_filltype(path.getFillType()));
}
pipelineBuilder->stencil()->setDisabled();
return true;
}
示例9: get_geometry
static bool get_geometry(const SkPath& path, const SkMatrix& m, PLSVertices& triVertices,
PLSVertices& quadVertices, GrResourceProvider* resourceProvider,
SkRect bounds) {
SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, m, bounds);
int contourCnt;
int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol);
if (maxPts <= 0) {
return 0;
}
SkPath linesOnlyPath;
linesOnlyPath.setFillType(path.getFillType());
SkSTArray<15, SkPoint, true> quadPoints;
SkPath::Iter iter(path, true);
bool done = false;
while (!done) {
SkPoint pts[4];
SkPath::Verb verb = iter.next(pts);
switch (verb) {
case SkPath::kMove_Verb:
SkASSERT(quadPoints.count() % 3 == 0);
for (int i = 0; i < quadPoints.count(); i += 3) {
add_quad(&quadPoints[i], quadVertices);
}
quadPoints.reset();
m.mapPoints(&pts[0], 1);
linesOnlyPath.moveTo(pts[0]);
break;
case SkPath::kLine_Verb:
m.mapPoints(&pts[1], 1);
linesOnlyPath.lineTo(pts[1]);
break;
case SkPath::kQuad_Verb:
m.mapPoints(pts, 3);
linesOnlyPath.lineTo(pts[2]);
quadPoints.push_back(pts[0]);
quadPoints.push_back(pts[1]);
quadPoints.push_back(pts[2]);
break;
case SkPath::kCubic_Verb: {
m.mapPoints(pts, 4);
SkSTArray<15, SkPoint, true> quads;
GrPathUtils::convertCubicToQuads(pts, kCubicTolerance, &quads);
int count = quads.count();
for (int q = 0; q < count; q += 3) {
linesOnlyPath.lineTo(quads[q + 2]);
quadPoints.push_back(quads[q]);
quadPoints.push_back(quads[q + 1]);
quadPoints.push_back(quads[q + 2]);
}
break;
}
case SkPath::kConic_Verb: {
m.mapPoints(pts, 3);
SkScalar weight = iter.conicWeight();
SkAutoConicToQuads converter;
const SkPoint* quads = converter.computeQuads(pts, weight, kConicTolerance);
int count = converter.countQuads();
for (int i = 0; i < count; ++i) {
linesOnlyPath.lineTo(quads[2 * i + 2]);
quadPoints.push_back(quads[2 * i]);
quadPoints.push_back(quads[2 * i + 1]);
quadPoints.push_back(quads[2 * i + 2]);
}
break;
}
case SkPath::kClose_Verb:
linesOnlyPath.close();
break;
case SkPath::kDone_Verb:
done = true;
break;
default: SkASSERT(false);
}
}
SkASSERT(quadPoints.count() % 3 == 0);
for (int i = 0; i < quadPoints.count(); i += 3) {
add_quad(&quadPoints[i], quadVertices);
}
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
GrUniqueKey::Builder builder(&key, kDomain, 2);
builder[0] = path.getGenerationID();
builder[1] = path.getFillType();
builder.finish();
GrTessellator::WindingVertex* windingVertices;
int triVertexCount = GrTessellator::PathToVertices(linesOnlyPath, 0, bounds, &windingVertices);
if (triVertexCount > 0) {
for (int i = 0; i < triVertexCount; i += 3) {
SkPoint p1 = windingVertices[i].fPos;
SkPoint p2 = windingVertices[i + 1].fPos;
SkPoint p3 = windingVertices[i + 2].fPos;
int winding = windingVertices[i].fWinding;
SkASSERT(windingVertices[i + 1].fWinding == winding);
SkASSERT(windingVertices[i + 2].fWinding == winding);
SkScalar cross = (p2 - p1).cross(p3 - p1);
SkPoint bloated[3] = { p1, p2, p3 };
if (cross < 0.0f) {
SkTSwap(p1, p3);
//.........这里部分代码省略.........
示例10: onDrawPath
bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) {
SkASSERT(!antiAlias);
SkASSERT(!stroke.isHairlineStyle());
GrDrawState* drawState = target->drawState();
SkASSERT(drawState->getStencil().isDisabled());
SkAutoTUnref<GrPath> p(fGpu->createPath(path));
SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(path.getFillType());
target->stencilPath(p, stroke, nonInvertedFill);
// TODO: Use built in cover operation rather than a rect draw. This will require making our
// fragment shaders be able to eat varyings generated by a matrix.
// fill the path, zero out the stencil
SkRect bounds = p->getBounds();
SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_ScalarHalf;
GrDrawState::AutoViewMatrixRestore avmr;
if (nonInvertedFill == path.getFillType()) {
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
kZero_StencilOp,
kZero_StencilOp,
kNotEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
*drawState->stencil() = kStencilPass;
} else {
GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
kZero_StencilOp,
kZero_StencilOp,
// We know our rect will hit pixels outside the clip and the user bits will be 0
// outside the clip. So we can't just fill where the user bits are 0. We also need to
// check that the clip bit is set.
kEqualIfInClip_StencilFunc,
0xffff,
0x0000,
0xffff);
SkMatrix vmi;
bounds.setLTRB(0, 0,
SkIntToScalar(drawState->getRenderTarget()->width()),
SkIntToScalar(drawState->getRenderTarget()->height()));
// mapRect through persp matrix may not be correct
if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
} else {
avmr.setIdentity(drawState);
bloat = 0;
}
*drawState->stencil() = kInvertedStencilPass;
}
bounds.outset(bloat, bloat);
target->drawSimpleRect(bounds, NULL);
target->drawState()->stencil()->setDisabled();
return true;
}
示例11: internalDrawPath
bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target,
GrPipelineBuilder* pipelineBuilder,
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
const GrStrokeInfo& origStroke,
bool stencilOnly) {
SkTCopyOnFirstWrite<GrStrokeInfo> stroke(origStroke);
SkScalar hairlineCoverage;
uint8_t newCoverage = 0xff;
if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) {
newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
if (!stroke->getStrokeRec().isHairlineStyle()) {
stroke.writable()->getStrokeRecPtr()->setHairlineStyle();
}
}
const bool isHairline = stroke->getStrokeRec().isHairlineStyle();
// Save the current xp on the draw state so we can reset it if needed
SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXPFactory()));
// face culling doesn't make sense here
SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace());
int passCount = 0;
const GrStencilSettings* passes[3];
GrPipelineBuilder::DrawFace drawFace[3];
bool reverse = false;
bool lastPassIsBounds;
if (isHairline) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
} else {
passes[0] = NULL;
}
lastPassIsBounds = false;
drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
} else {
if (single_pass_path(path, stroke->getStrokeRec())) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
} else {
passes[0] = NULL;
}
drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
lastPassIsBounds = false;
} else {
switch (path.getFillType()) {
case SkPath::kInverseEvenOdd_FillType:
reverse = true;
// fallthrough
case SkPath::kEvenOdd_FillType:
passes[0] = &gEOStencilPass;
if (stencilOnly) {
passCount = 1;
lastPassIsBounds = false;
} else {
passCount = 2;
lastPassIsBounds = true;
if (reverse) {
passes[1] = &gInvEOColorPass;
} else {
passes[1] = &gEOColorPass;
}
}
drawFace[0] = drawFace[1] = GrPipelineBuilder::kBoth_DrawFace;
break;
case SkPath::kInverseWinding_FillType:
reverse = true;
// fallthrough
case SkPath::kWinding_FillType:
if (fSeparateStencil) {
if (fStencilWrapOps) {
passes[0] = &gWindStencilSeparateWithWrap;
} else {
passes[0] = &gWindStencilSeparateNoWrap;
}
passCount = 2;
drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
} else {
if (fStencilWrapOps) {
passes[0] = &gWindSingleStencilWithWrapInc;
passes[1] = &gWindSingleStencilWithWrapDec;
} else {
passes[0] = &gWindSingleStencilNoWrapInc;
passes[1] = &gWindSingleStencilNoWrapDec;
}
// which is cw and which is ccw is arbitrary.
drawFace[0] = GrPipelineBuilder::kCW_DrawFace;
drawFace[1] = GrPipelineBuilder::kCCW_DrawFace;
passCount = 3;
}
if (stencilOnly) {
lastPassIsBounds = false;
//.........这里部分代码省略.........
示例12: onDrawPath
bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) {
SkASSERT(!antiAlias);
SkASSERT(!stroke.isHairlineStyle());
GrDrawState* drawState = target->drawState();
SkASSERT(drawState->getStencil().isDisabled());
SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
if (path.isInverseFillType()) {
GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
kZero_StencilOp,
kZero_StencilOp,
// We know our rect will hit pixels outside the clip and the user bits will be 0
// outside the clip. So we can't just fill where the user bits are 0. We also need to
// check that the clip bit is set.
kEqualIfInClip_StencilFunc,
0xffff,
0x0000,
0xffff);
drawState->setStencil(kInvertedStencilPass);
// fake inverse with a stencil and cover
target->stencilPath(p, convert_skpath_filltype(path.getFillType()));
GrDrawState::AutoViewMatrixRestore avmr;
SkRect bounds = SkRect::MakeLTRB(0, 0,
SkIntToScalar(drawState->getRenderTarget()->width()),
SkIntToScalar(drawState->getRenderTarget()->height()));
SkMatrix vmi;
// mapRect through persp matrix may not be correct
if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
bounds.outset(bloat, bloat);
} else {
avmr.setIdentity(drawState);
}
target->drawSimpleRect(bounds);
} else {
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
kZero_StencilOp,
kZero_StencilOp,
kNotEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
drawState->setStencil(kStencilPass);
target->drawPath(p, convert_skpath_filltype(path.getFillType()));
}
target->drawState()->stencil()->setDisabled();
return true;
}
示例13: makePath
Json::Value SkJSONCanvas::makePath(const SkPath& path) {
Json::Value result(Json::objectValue);
switch (path.getFillType()) {
case SkPath::kWinding_FillType:
result[SKJSONCANVAS_ATTRIBUTE_FILLTYPE] = SKJSONCANVAS_FILLTYPE_WINDING;
break;
case SkPath::kEvenOdd_FillType:
result[SKJSONCANVAS_ATTRIBUTE_FILLTYPE] = SKJSONCANVAS_FILLTYPE_EVENODD;
break;
case SkPath::kInverseWinding_FillType:
result[SKJSONCANVAS_ATTRIBUTE_FILLTYPE] = SKJSONCANVAS_FILLTYPE_INVERSEWINDING;
break;
case SkPath::kInverseEvenOdd_FillType:
result[SKJSONCANVAS_ATTRIBUTE_FILLTYPE] = SKJSONCANVAS_FILLTYPE_INVERSEEVENODD;
break;
}
Json::Value verbs(Json::arrayValue);
SkPath::Iter iter(path, false);
SkPoint pts[4];
SkPath::Verb verb;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
switch (verb) {
case SkPath::kLine_Verb: {
Json::Value line(Json::objectValue);
line[SKJSONCANVAS_VERB_LINE] = this->makePoint(pts[1]);
verbs.append(line);
break;
}
case SkPath::kQuad_Verb: {
Json::Value quad(Json::objectValue);
Json::Value coords(Json::arrayValue);
coords.append(this->makePoint(pts[1]));
coords.append(this->makePoint(pts[2]));
quad[SKJSONCANVAS_VERB_QUAD] = coords;
verbs.append(quad);
break;
}
case SkPath::kCubic_Verb: {
Json::Value cubic(Json::objectValue);
Json::Value coords(Json::arrayValue);
coords.append(this->makePoint(pts[1]));
coords.append(this->makePoint(pts[2]));
coords.append(this->makePoint(pts[3]));
cubic[SKJSONCANVAS_VERB_CUBIC] = coords;
verbs.append(cubic);
break;
}
case SkPath::kConic_Verb: {
Json::Value conic(Json::objectValue);
Json::Value coords(Json::arrayValue);
coords.append(this->makePoint(pts[1]));
coords.append(this->makePoint(pts[2]));
coords.append(Json::Value(iter.conicWeight()));
conic[SKJSONCANVAS_VERB_CONIC] = coords;
verbs.append(conic);
break;
}
case SkPath::kMove_Verb: {
Json::Value move(Json::objectValue);
move[SKJSONCANVAS_VERB_MOVE] = this->makePoint(pts[0]);
verbs.append(move);
break;
}
case SkPath::kClose_Verb:
verbs.append(Json::Value(SKJSONCANVAS_VERB_CLOSE));
break;
case SkPath::kDone_Verb:
break;
}
}
result[SKJSONCANVAS_ATTRIBUTE_VERBS] = verbs;
return result;
}
示例14: sk_fill_path
// clipRect has not been shifted up
void sk_fill_path(const SkPath& path, const SkIRect& clipRect, SkBlitter* blitter,
int start_y, int stop_y, int shiftEdgesUp, bool pathContainedInClip) {
SkASSERT(blitter);
SkIRect shiftedClip = clipRect;
shiftedClip.fLeft = SkLeftShift(shiftedClip.fLeft, shiftEdgesUp);
shiftedClip.fRight = SkLeftShift(shiftedClip.fRight, shiftEdgesUp);
shiftedClip.fTop = SkLeftShift(shiftedClip.fTop, shiftEdgesUp);
shiftedClip.fBottom = SkLeftShift(shiftedClip.fBottom, shiftEdgesUp);
SkEdgeBuilder builder;
int count = builder.build_edges(path, &shiftedClip, shiftEdgesUp, pathContainedInClip);
SkEdge** list = builder.edgeList();
if (0 == count) {
if (path.isInverseFillType()) {
/*
* Since we are in inverse-fill, our caller has already drawn above
* our top (start_y) and will draw below our bottom (stop_y). Thus
* we need to restrict our drawing to the intersection of the clip
* and those two limits.
*/
SkIRect rect = clipRect;
if (rect.fTop < start_y) {
rect.fTop = start_y;
}
if (rect.fBottom > stop_y) {
rect.fBottom = stop_y;
}
if (!rect.isEmpty()) {
blitter->blitRect(rect.fLeft << shiftEdgesUp,
rect.fTop << shiftEdgesUp,
rect.width() << shiftEdgesUp,
rect.height() << shiftEdgesUp);
}
}
return;
}
SkEdge headEdge, tailEdge, *last;
// this returns the first and last edge after they're sorted into a dlink list
SkEdge* edge = sort_edges(list, count, &last);
headEdge.fPrev = nullptr;
headEdge.fNext = edge;
headEdge.fFirstY = kEDGE_HEAD_Y;
headEdge.fX = SK_MinS32;
edge->fPrev = &headEdge;
tailEdge.fPrev = last;
tailEdge.fNext = nullptr;
tailEdge.fFirstY = kEDGE_TAIL_Y;
last->fNext = &tailEdge;
// now edge is the head of the sorted linklist
start_y = SkLeftShift(start_y, shiftEdgesUp);
stop_y = SkLeftShift(stop_y, shiftEdgesUp);
if (!pathContainedInClip && start_y < shiftedClip.fTop) {
start_y = shiftedClip.fTop;
}
if (!pathContainedInClip && stop_y > shiftedClip.fBottom) {
stop_y = shiftedClip.fBottom;
}
InverseBlitter ib;
PrePostProc proc = nullptr;
if (path.isInverseFillType()) {
ib.setBlitter(blitter, clipRect, shiftEdgesUp);
blitter = &ib;
proc = PrePostInverseBlitterProc;
}
// count >= 2 is required as the convex walker does not handle missing right edges
if (path.isConvex() && (nullptr == proc) && count >= 2) {
walk_simple_edges(&headEdge, blitter, start_y, stop_y);
} else {
walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc,
shiftedClip.right());
}
}
示例15: internalDrawPath
bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
const SkStrokeRec& origStroke,
GrDrawTarget* target,
bool stencilOnly) {
SkMatrix viewM = target->getDrawState().getViewMatrix();
SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
SkScalar hairlineCoverage;
if (IsStrokeHairlineOrEquivalent(*stroke, target->getDrawState().getViewMatrix(),
&hairlineCoverage)) {
uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage *
target->getDrawState().getCoverage());
target->drawState()->setCoverage(newCoverage);
if (!stroke->isHairlineStyle()) {
stroke.writable()->setHairlineStyle();
}
}
SkScalar tol = SK_Scalar1;
tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds());
int vertexCnt;
int indexCnt;
GrPrimitiveType primType;
GrDrawTarget::AutoReleaseGeometry arg;
if (!this->createGeom(path,
*stroke,
tol,
target,
&primType,
&vertexCnt,
&indexCnt,
&arg)) {
return false;
}
SkASSERT(NULL != target);
GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
GrDrawState* drawState = target->drawState();
bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
// face culling doesn't make sense here
SkASSERT(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
int passCount = 0;
const GrStencilSettings* passes[3];
GrDrawState::DrawFace drawFace[3];
bool reverse = false;
bool lastPassIsBounds;
if (stroke->isHairlineStyle()) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
} else {
passes[0] = NULL;
}
lastPassIsBounds = false;
drawFace[0] = GrDrawState::kBoth_DrawFace;
} else {
if (single_pass_path(path, *stroke)) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
} else {
passes[0] = NULL;
}
drawFace[0] = GrDrawState::kBoth_DrawFace;
lastPassIsBounds = false;
} else {
switch (path.getFillType()) {
case SkPath::kInverseEvenOdd_FillType:
reverse = true;
// fallthrough
case SkPath::kEvenOdd_FillType:
passes[0] = &gEOStencilPass;
if (stencilOnly) {
passCount = 1;
lastPassIsBounds = false;
} else {
passCount = 2;
lastPassIsBounds = true;
if (reverse) {
passes[1] = &gInvEOColorPass;
} else {
passes[1] = &gEOColorPass;
}
}
drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
break;
case SkPath::kInverseWinding_FillType:
reverse = true;
// fallthrough
case SkPath::kWinding_FillType:
if (fSeparateStencil) {
if (fStencilWrapOps) {
passes[0] = &gWindStencilSeparateWithWrap;
} else {
//.........这里部分代码省略.........