|
|

|
|
|
Listing 3 : Functions for
drawing and erasing objects and refreshing the display
|
void displayRefresh(void)
{
Drawable *drawablePtr; /* for iterating through lists */
int offsetX;
int offsetY;
/*
First erase the old images of the dirty objects
*/
for (drawablePtr = GS_dirtyList;
drawablePtr != NULL;
drawablePtr = drawablePtr->nextDirtyDrawablePtr)
{
/*
We only erase the image if there was an old
parent and it
is not dirty. Strictly speaking we should check the parentýs
parent and so on, but the extra work would probably not pay
off in terms of avoiding extra redraws.
*/
if ( (drawablePtr->oldParentPtr != NULL) &&
(drawablePtr->oldParentPtr->visible) &&
(!drawablePtr->oldParentPtr->drawable.dirty) )
{
offsetX = drawablePtr->oldParentPtr->absoluteLeft;
offsetY = drawablePtr->oldParentPtr->absoluteTop;
drawableErase(drawablePtr, offsetX,
offsetY);
}
} /* end for */
/*
The next step is to draw all of the dirty objects
*/
for (drawablePtr = GS_dirtyList;
drawablePtr != NULL;
drawablePtr = drawablePtr->nextDirtyDrawablePtr)
{
/*
We only draw the image if there is a parent and it is not
dirty. Strictly speaking we should check the parentýs parent
and so on, but the extra work would probably not pay off.
*/
if ( (drawablePtr->parentPtr != NULL) &&
(drawablePtr->parentPtr->visible) &&
(!drawablePtr->parentPtr->drawable.dirty) )
{
offsetX = drawablePtr->parentPtr->absoluteLeft;
offsetY = drawablePtr->parentPtr->absoluteTop;
drawableDraw(drawablePtr, offsetX, offsetY);
} /* end if */
} /* end for */
/*
Now that the objects have been updated the dirty flag can be
cleared. These flags should not be cleared in one of the earlier
loops because they are used for optimizations in the drawableDraw
function. Note that the links of the chain are not set to NULL.
This does not matter because they will get overwritten if it is put
on the chain again.
*/
drawablePtr = GS_dirtyList;
for (drawablePtr = GS_dirtyList;
drawablePtr != NULL;
drawablePtr = drawablePtr->nextDirtyDrawablePtr)
{
drawablePtr->dirty = FALSE;
}
GS_dirtyList = NULL;
}
void drawableDraw(Drawable *drawablePtr, int offsetX, int offsetY)
{
/* draw should never be called for an orphan */
assert(drawablePtr->parentPtr != NULL);
switch (drawablePtr->type)
{
case
CONTAINER:
containerDraw((Container *)drawablePtr, offsetX, offsetY);
break;
case BOX:
boxDraw((Box *)drawablePtr, offsetX, offsetY);
break;
case CIRCLE:
circleDraw((Circle *)drawablePtr, offsetX, offsetY);
break;
case LINE:
lineDraw((Line *)drawablePtr, offsetX, offsetY);
break;
case TEXT:
textDraw((Text *)drawablePtr, offsetX, offsetY);
break;
default:
assert(FALSE);
}
/*
Update the oldParent for the time when we will want to
erase this
drawable
*/
drawablePtr->oldParentPtr = drawablePtr->parentPtr;
}
/*
This function decides what kind of shape we have and chooses an
erase routine based on the type field of the Drawable structure.
{
if (drawablePtr->oldParentPtr == NULL)
{
/*
If there is no old parent then there is nowhere to
erase from.
*/
return;
}
switch (drawablePtr->type)
{
case CONTAINER:
containerErase((Container *)drawablePtr, offsetX, offsetY);
break;
case BOX:
boxErase((Box
*)drawablePtr, offsetX, offsetY);
break;
case CIRCLE:
circleErase((Circle *)drawablePtr, offsetX, offsetY);
break;
case LINE:
lineErase((Line *)drawablePtr, offsetX, offsetY);
break;
case TEXT:
textErase((Text *)drawablePtr, offsetX, offsetY);
break;
default:
assert(FALSE);
}
}
void boxDraw(Box * boxPtr, int offsetX, int offsetY)
{
int top;
int left;
int right;
int bottom;
assert(boxPtr->drawable.parentPtr != NULL);
left = offsetX + boxPtr->drawable.area.left;
top = offsetY + boxPtr->drawable.area.top;
right = offsetX + boxPtr->drawable.area.right;
bottom = offsetY + boxPtr->drawable.area.bottom;
#ifdef USING_BGI
setcolor(boxPtr->drawable.color);
if (boxPtr->filled)
{
setfillstyle(SOLID_FILL, boxPtr->fillColor);
fillRectangle(left, top, right, bottom);
}
else
{
setfillstyle(EMPTY_FILL, boxPtr->fillColor);
rectangle(left, top, right, bottom);
}
#endif
/*
We have to record all of the old stuff now, so it can be used on
the
next erase
*/
boxPtr->drawable.oldArea = boxPtr->drawable.area;
boxPtr->oldFilled = boxPtr->filled;
}
/*
This function will draw over a box in the background color of
the parent, and therefore erase the box. The background color
of the old parent is used because the current parent may be
different, and the image that we are trying to remove is in the
old parent.
If the old parent has moved or changed color, then this routine
would not work. This is not a problem, because if the old parent
had
moved then it would be marked dirty and this routine would
never be called. The redraw of the old parent would clean any
image of the box that remained.
*/
void boxErase(Box *boxPtr, int offsetX, int offsetY)
{
int backgroundColor;
int absoluteLeft = offsetX + boxPtr->drawable.oldArea.left;
int absoluteTop = offsetY + boxPtr->drawable.oldArea.top;
int absoluteRight = offsetX + boxPtr->drawable.oldArea.right;
int absoluteBottom = offsetY + boxPtr->drawable.oldArea.bottom;
backgroundColor =
boxPtr->drawable.oldParentPtr->drawable.color;
#ifdef USING_BGI
setcolor(backgroundColor);
if (boxPtr->oldFilled)
{
setfillstyle(SOLID_FILL, backgroundColor);
fillRectangle(absoluteLeft, absoluteTop,
absoluteRight, absoluteBottom);
}
else
{
setfillstyle(EMPTY_FILL, backgroundColor);
rectangle(absoluteLeft, absoluteTop,
absoluteRight, absoluteBottom);
}
#endif
}
/*
|
Back
|
|
|
|
|