📄 seed1.c
字号:
DrawList:
CurrentSegmentList = blockPtr;
blockPtr = blockPtr->NextBlock; /* point to first segment */
scanLineP1 = ScanLine + 1;
i = blitRecord.blitCnt;
if (i == MAX_RECTS)
{ /* draw one full burst, and resets for the next one */
FillPrimitive(&blitRecord);
sRectPtr = (rect *) (blitRecord.blitList);
i = 0;
}
while (1)
{
for (;i < MAX_RECTS; i++)
{
sRectPtr->Xmin = (short) blockPtr->sXmin; /* rect left edge */
sRectPtr->Xmax = (short) blockPtr->sXmax; /* rect right edge */
sRectPtr->Ymin = ScanLine; /* rect top edge */
sRectPtr->Ymax = scanLineP1; /* rect bottom edge */
sRectPtr++; /* point to the next rect in blitList */
blockPtr = blockPtr->NextBlock; /* point to next segment */
if (blockPtr->sXmin == 0x7FFF) goto DrawLoopDone; /* sentinel? */
}
/* draw one full burst, and reset for the next one */
blitRecord.blitCnt = MAX_RECTS;
FillPrimitive(&blitRecord);
sRectPtr = (rect *) (blitRecord.blitList);
i = 0;
}
DrawLoopDone:
/* # of count of rects just processed */
blitRecord.blitCnt = (short) ((((long) sRectPtr) - blitRecord.blitList) >> 3);
/* now make up pShadow as the current segment list, minus the old
shadow with each segment widened by 1 (this represents all the
pixels we haven't already processed or eliminated in the backward dir) */
blockPtrDN = pShadow->NextBlock; /* start of old shadow list */
if (AllocBlock() == NULL) /* get block for backshadow list header */
{ /* not enough memory */
grafErrValue = c_SeedFill + c_OutofMem;
nuGrafErr(grafErrValue);
return;
}
blockPtrBE = blockPtr;
pShadow = blockPtr; /* this will become the new shadow */
pShadow->sXmin = 0x7FFF; /* also will link to next to become */
pShadow->sXmax = 0x7FFF; /* the sentinel */
blockPtr = CurrentSegmentList->NextBlock; /* start of current
segment list */
while ((wXmin = (short) blockPtr->sXmin) != 0x7FFF)
{
while (wXmin > blockPtrDN->sXmax)
{ /* skip through shadows until we find one that isn't
entirely to the left */
blockPtrCE = blockPtrDN->NextBlock;
blockPtrDN->NextBlock = FreeBlocks;
FreeBlocks = blockPtrDN;
blockPtrDN = blockPtrCE;
} /* will terminate because of sentinel */
/* we've found a shadow that's not wholly to the left. We know
the current segment can't be to the right of the shadow (we just
checked that), so start by checking whether it's to the left */
CheckToLeft:
if ((blockPtr->sXmax >= blockPtrDN->sXmin) &&
(blockPtrDN->sXmin != 0x7FFF))
{ /* the segment and the shadow overlap */
tempEdge = blockPtrDN->sXmin - 1; /* right edge */
if (wXmin < tempEdge)
{ /* make the part of the segment that sticks out to the
left of the shadow into a new segment */
blockPtrST = blockPtr; /* save current pointer */
if (AllocBlock() == NULL) /* get block for this segment */
{ /* not enough memory */
grafErrValue = c_SeedFill + c_OutofMem;
nuGrafErr(grafErrValue);
return;
}
blockPtrCE = blockPtr; /* restore our place in current
list */
blockPtr = blockPtrST;
blockPtrBE->NextBlock = blockPtrCE; /* link to the
backshadow list */
blockPtrBE = blockPtrCE; /* point to the new block */
blockPtrBE->sXmin = wXmin;
blockPtrBE->sXmax = tempEdge;
}
/* figure out whether the current seg extends to the right of
this shadow segment and handle accordingly */
if ((blockPtr->sXmax - 1) <= blockPtrDN->sXmax)
{ /* the current seg doesn't reach beyond this shadow seg
and we're done with it; time to do the next segment */
blockPtr = blockPtr->NextBlock;
continue;
}
/* we're done with the shadow and can trim the segment to the
part that extends past the shadow and continue with that */
wXmin = blockPtrDN->sXmax + 1;
blockPtrCE = blockPtrDN->NextBlock;
blockPtrDN->NextBlock = FreeBlocks;
FreeBlocks = blockPtrDN;
blockPtrDN = blockPtrCE;
goto CheckToLeft; /* we know there's no shadow entirely to
the left of this segment, because we're smack dab next to the
previous shadow, and the next shadow has to be to the right of
that shadow, so we can skip that check */
}
blockPtrST = blockPtr; /* save block pointer */
if (AllocBlock() == NULL) /* get block for this segment */
{ /* not enough memory */
grafErrValue = c_SeedFill + c_OutofMem;
nuGrafErr(grafErrValue);
return;
}
blockPtrCE = blockPtr; /* restore our place in current list */
blockPtr = blockPtrST;
blockPtrBE->NextBlock = blockPtrCE; /* link to the backshadow list */
blockPtrBE = blockPtrCE; /* point to the new block */
blockPtrBE->sXmin = wXmin; /* left edge */
blockPtrBE->sXmax = blockPtr->sXmax; /* right edge */
blockPtr = blockPtr->NextBlock; /* move on to the next segment
in the current segment list */
}
FreeList(); /* free up the remaining blocks in the old shadow list
(the sentinel, at a minimum) */
blockPtrDN = pShadow; /* head of the new shadow list */
/* now decide whether the backshadow is good for anything */
if (blockPtrBE == blockPtrDN)
{ /* the new shadow is empty */
blockPtrST = FreeBlocks; /* return the sentinel to the free list */
FreeBlocks = blockPtrBE;
blockPtrBE = blockPtrST;
blockPtrDN->NextBlock = blockPtrBE;
blockPtrDN = CurrentSegmentList; /* make the current segment */
pShadow = blockPtrDN; /* list the shadow for next time */
} /* continue in the same direction */
else
{
blockPtrBE->NextBlock = blockPtrDN; /* link the head of the new
list back to the end through the sentinel */
blockPtrDN = CurrentSegmentList; /* save the current segment
list as the pushed shadow for when we continue in this direction */
if (PushState() == 0) /* save the current state */
{ /* not enough memory */
grafErrValue = c_SeedFill + c_OutofMem;
nuGrafErr(grafErrValue);
return;
}
ForwardLimit = BackwardLimit; /* new scanning limit */
BackwardLimit = ScanLine + sDirection; /* where to stop if the
scan reverses again and comes back this way */
FLimitPtr = BLimitPtr; /* new segment list to add to if limit
is reached */
BLimitPtr = CurrentSegmentList; /* segment list to add to if
the above occurs */
sDirection = -sDirection; /* reverse direction */
blockPtrDN = pShadow; /* point to shadow sentinel */
}
/* Main seed fill loop. */
while (1)
{
blockPtrDN = blockPtrDN->NextBlock; /* point past sentinel to
first shadow */
ScanLine += sDirection; /* advance one scan line up or down */
if (ScanLine != ForwardLimit)
{ /* have not reached the current limit in this direction */
blockPtrDN = pShadow; /* generate the segment list from
the shadow */
if (ScanOutSegList() == 0)
{ /* not enough memory */
grafErrValue = c_SeedFill + c_OutofMem;
nuGrafErr(grafErrValue);
return;
}
if (blockPtr != blockPtr->NextBlock) goto DrawList;
/* list is empty, done with this direction of scanning */
blockPtr->NextBlock = FreeBlocks; /* free up the sentinel */
FreeBlocks = blockPtr;
blockPtrDN = pShadow->NextBlock; /* point to the shadow
that just proved to lead nowhere */
FreeList(); /* free the shadow */
if (PopState() == 0) /* none left to pop, so we're done */
{ /* Draw any remaining rects in the blitRcd. */
FillPrimitive(&blitRecord);
return;
}
continue; /* in the new direction */
}
/* have reached the current limit in this direction */
if (ScanLine == lmtR.Ymax)
{ /* we're at the bottom of the limit rect. We'll never fill
past this point, so this shadow is of no use; dump it so we
don't waste space */
FreeList();
}
else
{
if (ScanLine < lmtR.Ymin) /* all done */
{ /* Draw any remaining rects in the blitRcd. */
FillPrimitive(&blitRecord);
return;
}
/* add current shadow to forward limit shadow for whenever
we return here */
/* ***assumes non-empty shadow!*** */
blockPtrBE = FLimitPtr; /* point to forward limit segment
list header */
do{
blockPtr = blockPtrBE->NextBlock;
while (blockPtrDN->sXmin >= blockPtr->sXmin)
{ /* find the limit */
blockPtrBE = blockPtr;
blockPtr = blockPtrBE->NextBlock;
}
blockPtrBE->NextBlock = blockPtrDN; /* link in shadow */
blockPtrBE = blockPtrDN->NextBlock; /* segment */
blockPtrDN->NextBlock = blockPtr;
blockPtr = blockPtrBE;
blockPtrBE = blockPtrDN; /* the shadow segment is now
the current forward limit element */
blockPtrDN = blockPtr; /* next shadow segment */
} while (blockPtrDN->sXmin != 0x7FFF); /* is the next shadow
seg the sentinel? */
blockPtrDN->NextBlock = FreeBlocks; /* return the shadow */
FreeBlocks = blockPtrDN; /* sentinel to the free block list */
}
if (PopState() == 0) break; /* none left to pop, so we're done */
} /* continue in the new direction */
/* Draw any remaining rects in the blitRcd. */
FillPrimitive(&blitRecord);
return;
}
/* Function NotMatchBoundaryColor returns 1 if pixel at qualifyX,
WorkingScanLine is fillable (not the boundary color), else 0. */
int NotMatchBoundaryColor(void)
{
if (GetPixelPrimitive(qualifyX, WorkingScanLine, blitRecord.blitDmap)
== boundaryColor) return(0);
return(1);
}
/* Function MatchSeedColor returns 1 if pixel at qualifyX, WorkingScanLine
is fillable (the seed color), else 0. */
int MatchSeedColor(void)
{
if (GetPixelPrimitive(qualifyX, WorkingScanLine, blitRecord.blitDmap)
== SeedColor) return(1);
return(0);
}
/* Function AllocBlock allocates a block from the memory pool. The end of
the block list (out of free blocks) is marked by a return value of 0. */
int AllocBlock(void)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -