/** Compare two edges incident to the same endpoint. * @param e1 is the index of a valid edge * @param e2 is the index of a valid edge * @param u is the index of a vertex that both edges are incident to * @return -1 if u's mate in e1 is less than u's mate in e2; * return +1 if u's mate in e1 is greater than than u's mate in e2. * return 0 if u's mate in e1 is equal to its mate in e2. */ int Graph::ecmp(edge e1, edge e2, vertex u) const { assert(validEdge(e1) && validEdge(e2) && validVertex(u) && (u == left(e1) || u == right(e1)) && (u == left(e2) || u == right(e2))); if (mate(u,e1) < mate(u,e2)) return -1; else if (mate(u,e1) > mate(u,e2)) return 1; else return 0; }
/** Remove an edge from the Graph. * @param e is the edge to be removed. * @return true on success, false on failure */ bool Graph::remove(edge e) { assert(validEdge(e)); edges->swap(e); vertex u = evec[e].l; fe[u] = adjLists->remove(2*e,fe[u]); u = evec[e].r; fe[u] = adjLists->remove(2*e+1,fe[u]); evec[e].l = 0; return true; }
bool GrTesselatedPathRenderer::onDrawPath(const SkPath& path, GrPathFill fill, const GrVec* translate, GrDrawTarget* target, GrDrawState::StageMask stageMask, bool antiAlias) { GrDrawTarget::AutoStateRestore asr(target); GrDrawState* drawState = target->drawState(); // face culling doesn't make sense here GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace()); GrMatrix viewM = drawState->getViewMatrix(); GrScalar tol = GR_Scalar1; tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds()); GrScalar tolSqd = GrMul(tol, tol); int subpathCnt; int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol); GrVertexLayout layout = 0; for (int s = 0; s < GrDrawState::kNumStages; ++s) { if ((1 << s) & stageMask) { layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); } } bool inverted = GrIsFillInverted(fill); if (inverted) { maxPts += 4; subpathCnt++; } if (maxPts > USHRT_MAX) { return false; } SkAutoSTMalloc<8, GrPoint> baseMem(maxPts); GrPoint* base = baseMem; GrPoint* vert = base; GrPoint* subpathBase = base; SkAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt); GrPoint pts[4]; SkPath::Iter iter(path, false); bool first = true; int subpath = 0; for (;;) { switch (iter.next(pts)) { case kMove_PathCmd: if (!first) { subpathVertCount[subpath] = vert-subpathBase; subpathBase = vert; ++subpath; } *vert = pts[0]; vert++; break; case kLine_PathCmd: *vert = pts[1]; vert++; break; case kQuadratic_PathCmd: { GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], tolSqd, &vert, GrPathUtils::quadraticPointCount(pts, tol)); break; } case kCubic_PathCmd: { GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], tolSqd, &vert, GrPathUtils::cubicPointCount(pts, tol)); break; } case kClose_PathCmd: break; case kEnd_PathCmd: subpathVertCount[subpath] = vert-subpathBase; ++subpath; // this could be only in debug goto FINISHED; } first = false; } FINISHED: if (NULL != translate && 0 != translate->fX && 0 != translate->fY) { for (int i = 0; i < vert - base; i++) { base[i].offset(translate->fX, translate->fY); } } if (inverted) { GrRect bounds; GrAssert(NULL != drawState->getRenderTarget()); bounds.setLTRB(0, 0, GrIntToScalar(drawState->getRenderTarget()->width()), GrIntToScalar(drawState->getRenderTarget()->height())); GrMatrix vmi; if (drawState->getViewInverse(&vmi)) { vmi.mapRect(&bounds); } *vert++ = GrPoint::Make(bounds.fLeft, bounds.fTop); *vert++ = GrPoint::Make(bounds.fLeft, bounds.fBottom); *vert++ = GrPoint::Make(bounds.fRight, bounds.fBottom); *vert++ = GrPoint::Make(bounds.fRight, bounds.fTop); subpathVertCount[subpath++] = 4; } GrAssert(subpath == subpathCnt); GrAssert((vert - base) <= maxPts); size_t count = vert - base; if (count < 3) { return true; } if (subpathCnt == 1 && !inverted && path.isConvex()) { if (antiAlias) { GrEdgeArray edges; GrMatrix inverse, matrix = drawState->getViewMatrix(); drawState->getViewInverse(&inverse); count = computeEdgesAndIntersect(matrix, inverse, base, count, &edges, 0.0f); size_t maxEdges = target->getMaxEdges(); if (count == 0) { return true; } if (count <= maxEdges) { // All edges fit; upload all edges and draw all verts as a fan target->setVertexSourceToArray(layout, base, count); drawState->setEdgeAAData(&edges[0], count); target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count); } else { // Upload "maxEdges" edges and verts at a time, and draw as // separate fans for (size_t i = 0; i < count - 2; i += maxEdges - 2) { edges[i] = edges[0]; base[i] = base[0]; int size = GR_CT_MIN(count - i, maxEdges); target->setVertexSourceToArray(layout, &base[i], size); drawState->setEdgeAAData(&edges[i], size); target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size); } } drawState->setEdgeAAData(NULL, 0); } else { target->setVertexSourceToArray(layout, base, count); target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count); } return true; } if (antiAlias) { // Run the tesselator once to get the boundaries. GrBoundaryTess btess(count, fill_type_to_glu_winding_rule(fill)); btess.addVertices(base, subpathVertCount, subpathCnt); GrMatrix inverse, matrix = drawState->getViewMatrix(); if (!drawState->getViewInverse(&inverse)) { return false; } if (btess.vertices().count() > USHRT_MAX) { return false; } // Inflate the boundary, and run the tesselator again to generate // interior polys. const GrPointArray& contourPoints = btess.contourPoints(); const GrIndexArray& contours = btess.contours(); GrEdgePolygonTess ptess(contourPoints.count(), GLU_TESS_WINDING_NONZERO, matrix); size_t i = 0; Sk_gluTessBeginPolygon(ptess.tess(), &ptess); for (int contour = 0; contour < contours.count(); ++contour) { int count = contours[contour]; GrEdgeArray edges; int newCount = computeEdgesAndIntersect(matrix, inverse, &btess.contourPoints()[i], count, &edges, 1.0f); Sk_gluTessBeginContour(ptess.tess()); for (int j = 0; j < newCount; j++) { ptess.addVertex(contourPoints[i + j], ptess.vertices().count()); } i += count; Sk_gluTessEndContour(ptess.tess()); } Sk_gluTessEndPolygon(ptess.tess()); if (ptess.vertices().count() > USHRT_MAX) { return false; } // Draw the resulting polys and upload their edge data. drawState->enableState(GrDrawState::kEdgeAAConcave_StateBit); const GrPointArray& vertices = ptess.vertices(); const GrIndexArray& indices = ptess.indices(); const GrDrawState::Edge* edges = ptess.edges(); GR_DEBUGASSERT(indices.count() % 3 == 0); for (int i = 0; i < indices.count(); i += 3) { GrPoint tri_verts[3]; int index0 = indices[i]; int index1 = indices[i + 1]; int index2 = indices[i + 2]; tri_verts[0] = vertices[index0]; tri_verts[1] = vertices[index1]; tri_verts[2] = vertices[index2]; GrDrawState::Edge tri_edges[6]; int t = 0; const GrDrawState::Edge& edge0 = edges[index0 * 2]; const GrDrawState::Edge& edge1 = edges[index0 * 2 + 1]; const GrDrawState::Edge& edge2 = edges[index1 * 2]; const GrDrawState::Edge& edge3 = edges[index1 * 2 + 1]; const GrDrawState::Edge& edge4 = edges[index2 * 2]; const GrDrawState::Edge& edge5 = edges[index2 * 2 + 1]; if (validEdge(edge0) && validEdge(edge1)) { tri_edges[t++] = edge0; tri_edges[t++] = edge1; } if (validEdge(edge2) && validEdge(edge3)) { tri_edges[t++] = edge2; tri_edges[t++] = edge3; } if (validEdge(edge4) && validEdge(edge5)) { tri_edges[t++] = edge4; tri_edges[t++] = edge5; } drawState->setEdgeAAData(&tri_edges[0], t); target->setVertexSourceToArray(layout, &tri_verts[0], 3); target->drawNonIndexed(kTriangles_PrimitiveType, 0, 3); } drawState->setEdgeAAData(NULL, 0); drawState->disableState(GrDrawState::kEdgeAAConcave_StateBit); return true; } GrPolygonTess ptess(count, fill_type_to_glu_winding_rule(fill)); ptess.addVertices(base, subpathVertCount, subpathCnt); const GrPointArray& vertices = ptess.vertices(); const GrIndexArray& indices = ptess.indices(); if (indices.count() > 0) { target->setVertexSourceToArray(layout, vertices.begin(), vertices.count()); target->setIndexSourceToArray(indices.begin(), indices.count()); target->drawIndexed(kTriangles_PrimitiveType, 0, 0, vertices.count(), indices.count()); } return true; }