Example #1
0
SEGMENTH CombinePolygonPieces(SEGMENTH *A1, SEGMENTH *B1,
							  Boolean keepAinB, Boolean keepAnotinB,
							  Boolean keepBinA, Boolean keepBnotinA)
{
	long i, j, err, numSegsA, numSegsB, numSegsC = 0;
	WorldPoint m;
	SEGMENTH C = 0, A2 = 0, B2 = 0, *A = 0, *B = 0;
	
	err = 0;
	
	numSegsA = _GetHandleSize((Handle)*A1) / sizeof(Segment);
	numSegsB = _GetHandleSize((Handle)*B1) / sizeof(Segment);
	
	A2 = (SEGMENTH)_NewHandle(numSegsA * sizeof(Segment));
	if (_MemError()) { TechError("CombinePolygonPieces()", "_NewHandle()", 0); goto done; }
	for (i = 0 ; i < numSegsA ; i++)
		INDEXH(A2, i) = INDEXH(*A1, i);
	A = &A2;
	
	B2 = (SEGMENTH)_NewHandle(numSegsB * sizeof(Segment));
	if (_MemError()) { TechError("CombinePolygonPieces()", "_NewHandle()", 0); goto done; }
	for (i = 0 ; i < numSegsB ; i++)
		INDEXH(B2, i) = INDEXH(*B1, i);
	B = &B2;
	
	for (i = 0 ; i < numSegsA ; i++)
		for (j = 0 ; j < numSegsB ; j++)
			if (SegmentTouchesSegment(INDEXH(*A, i), INDEXH(*B, j)) &&
				!SameSegmentEndPoints(INDEXH(*A, i), INDEXH(*B, j))) {
				m = PointOfIntersection(INDEXH(*A, i), INDEXH(*B, j));
				if (err = InsertSegment(A, &numSegsA, i, m)) goto done;
				if (err = InsertSegment(B, &numSegsB, j, m)) goto done;
			}
	
	C = (SEGMENTH)_NewHandle(0);
	if (_MemError()) { TechError("CombinePolygonPieces()", "_NewHandle()", 0); goto done; }
	
	for (i = 0 ; i < numSegsA ; i++) {
		m = Midpoint(INDEXH(*A, i));
		if ((keepAinB && PointInPolygon(m, *B, numSegsB, TRUE)) ||
			(keepAnotinB && !PointInPolygon(m, *B, numSegsB, TRUE)))
			if (err = AddSegment(&C, &numSegsC, INDEXH(*A, i))) goto done;
	}
	for (j = 0 ; j < numSegsB ; j++) {
		m = Midpoint(INDEXH(*B, j));
		if ((keepBinA && PointInPolygon(m, *A, numSegsA, TRUE)) ||
			(keepBnotinA && !PointInPolygon(m, *A, numSegsA, TRUE)))
			if (err = AddSegment(&C, &numSegsC, INDEXH(*B, j))) goto done;
	}
	
	SortSegments(C, numSegsC);
	
	done:
		if (A2) DisposeHandle((Handle)A2);
		if (B2) DisposeHandle((Handle)B2);
		if (err && C) DisposeHandle((Handle)C);
		
		return err ? 0 : C;
}
Example #2
0
// FIXME : add this as a member of SkPath
void Simplify(const SkPath& path, SkPath* result) {
#if DEBUG_SORT || DEBUG_SWAP_TOP
    gDebugSortCount = gDebugSortCountDefault;
#endif
    // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
    result->reset();
    result->setFillType(SkPath::kEvenOdd_FillType);
    SkPathWriter simple(*result);

    // turn path into list of segments
    SkTArray<SkOpContour> contours;
    SkOpEdgeBuilder builder(path, contours);
    builder.finish();
    SkTDArray<SkOpContour*> contourList;
    MakeContourList(contours, contourList, false, false);
    SkOpContour** currentPtr = contourList.begin();
    if (!currentPtr) {
        return;
    }
    SkOpContour** listEnd = contourList.end();
    // find all intersections between segments
    do {
        SkOpContour** nextPtr = currentPtr;
        SkOpContour* current = *currentPtr++;
        if (current->containsCubics()) {
            AddSelfIntersectTs(current);
        }
        SkOpContour* next;
        do {
            next = *nextPtr++;
        } while (AddIntersectTs(current, next) && nextPtr != listEnd);
    } while (currentPtr != listEnd);
    // eat through coincident edges
    CoincidenceCheck(&contourList, 0);
    FixOtherTIndex(&contourList);
    SortSegments(&contourList);
#if DEBUG_ACTIVE_SPANS
    DebugShowActiveSpans(contourList);
#endif
    // construct closed contours
    if (builder.xorMask() == kWinding_PathOpsMask ? bridgeWinding(contourList, &simple)
                : !bridgeXor(contourList, &simple))
    {  // if some edges could not be resolved, assemble remaining fragments
        SkPath temp;
        temp.setFillType(SkPath::kEvenOdd_FillType);
        SkPathWriter assembled(temp);
        Assemble(simple, &assembled);
        *result = *assembled.nativePath();
    }
}
Example #3
0
bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
#if DEBUG_SHOW_TEST_NAME
    char* debugName = DEBUG_FILENAME_STRING;
    if (debugName && debugName[0]) {
        SkPathOpsDebug::BumpTestName(debugName);
        SkPathOpsDebug::ShowPath(one, two, op, debugName);
    }
#endif
    op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()];
    SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isInverseFillType()]
            ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType;
    const SkPath* minuend = &one;
    const SkPath* subtrahend = &two;
    if (op == kReverseDifference_PathOp) {
        minuend = &two;
        subtrahend = &one;
        op = kDifference_PathOp;
    }
#if DEBUG_SORT || DEBUG_SWAP_TOP
    SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault;
#endif
    // turn path into list of segments
    SkTArray<SkOpContour> contours;
    // FIXME: add self-intersecting cubics' T values to segment
    SkOpEdgeBuilder builder(*minuend, contours);
    const int xorMask = builder.xorMask();
    builder.addOperand(*subtrahend);
    if (!builder.finish()) {
        return false;
    }
    result->reset();
    result->setFillType(fillType);
    const int xorOpMask = builder.xorMask();
    SkTArray<SkOpContour*, true> contourList;
    MakeContourList(contours, contourList, xorMask == kEvenOdd_PathOpsMask,
            xorOpMask == kEvenOdd_PathOpsMask);
    SkOpContour** currentPtr = contourList.begin();
    if (!currentPtr) {
        return true;
    }
    SkOpContour** listEnd = contourList.end();
    // find all intersections between segments
    do {
        SkOpContour** nextPtr = currentPtr;
        SkOpContour* current = *currentPtr++;
        if (current->containsCubics()) {
            AddSelfIntersectTs(current);
        }
        SkOpContour* next;
        do {
            next = *nextPtr++;
        } while (AddIntersectTs(current, next) && nextPtr != listEnd);
    } while (currentPtr != listEnd);
    // eat through coincident edges

    int total = 0;
    int index;
    for (index = 0; index < contourList.count(); ++index) {
        total += contourList[index]->segments().count();
    }
#if DEBUG_SHOW_WINDING
    SkOpContour::debugShowWindingValues(contourList);
#endif
    CoincidenceCheck(&contourList, total);
#if DEBUG_SHOW_WINDING
    SkOpContour::debugShowWindingValues(contourList);
#endif
    FixOtherTIndex(&contourList);
    CheckEnds(&contourList);
    CheckTiny(&contourList);
    SortSegments(&contourList);
#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
    DebugShowActiveSpans(contourList);
#endif
    // construct closed contours
    SkPathWriter wrapper(*result);
    bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper);
    {  // if some edges could not be resolved, assemble remaining fragments
        SkPath temp;
        temp.setFillType(fillType);
        SkPathWriter assembled(temp);
        Assemble(wrapper, &assembled);
        *result = *assembled.nativePath();
        result->setFillType(fillType);
    }
    return true;
}