This routine takes the supplied (unclipped) bounding rectangle, intersects it with each of the clip rectangles in the DC and accumulates each of the clipped bounds into the active SCAs. The supplied bounding rectangle can be in one of the following types of coordinates:
16-bit AI coordinates (COORD_AI)
The ulCoordtype field specifies which of these coordinates is being supplied.
AccumulateScreenBoundsThroughClips can be called from the same point in drawing functions as the ordinary (unclipped) bounds are accumulated. This minimizes the complexity and number of changes required in the main drawing code. Before accumulating the bounding rectangle, according to the following accumulation algorithm, the coordinate conversion (if required) to exclusive SCREEN coordinates and the clipping of the passed rectangle must be performed. The clipping can be done against the DC cache clip rectangles, or it may require a call back to the Graphics Engine to get the clip set. When a rectangle is added into an SCA, it is done in such a way as to minimize the increase in area of the SCA.
The following accumulation algorithm accomplishes this:
for (pscaCurrent = each SCA in the linked list) : : // First check whether the new rect is already contained within this SCA : for (rclCurrent = each rectangle in current SCA) : : if rclNew lies completely within rclCurrent : : : no more work - skip straight to next SCA : : endif : endfor : // We have to add the rectangle to the SCA. : // First see if there is free space for the rectangle within the SCA. : if pscaCurrent->cRects < MAX_SCA_RECTS : : copy rect into SCA : : calculate size and store in SCA : : increment pscaCurrent->cRects : else : : // All of the SCA rects are used. : : // Copy the new rect into the SCA at position (MAX_SCA_RECTS+1) and the : : // problem then becomes: : : // We have MAX_SCA_RECTS+1 rectangles, which we have to reduce : : // to MAX_SCA_RECTS by merging two of the rectangles into a single rectangle. : : // The pair of rects that we merge are the two that will cause the smallest : : // increase in area. : : initialize ulSmallestAreaIncrease to be maximum possible value : : for (iRect1 = each rectangle in the SCA) : : : for (iRect2 = iRect1+1 to MAX_SCA_RECTS+1) : : : // This inner loop is the performance bottleneck. : : : // Make it as fast as possible, if you can!! : : : : if area increase of (iRect1,iRect2) merged < ulSmallestAreaIncrease : : : : : set ulSmallestAreaIncrease to be area increase of (iRect1,iRect2) merged : : : : : set best pair of rects to be (iRect1,iRect2) : : : : endif : : : endfor : : endfor : : : : merge best pair of rects found into the slot originally occupied by Rect1 : : if rclNew was not one of those merged : : : copy rclNew into vacant slot made by merging pair : : endif : endif endfor
When change-area tracking is active, this routine is called by every function that draws to the screen. Therefore, the routine must be as efficient as possible (particularly in the inner loop) to minimize the hit on performance.