[comp.windows.x] Inconsistencies between fill & line rasterization algorithms

johnf@apollo.UUCP (06/09/87)

On looking at the X version 11 description of which pixels constitute the
"interior" of a region to be filled, I notice a discrepancy between the
decision procedure used to decide what to do when a pixel centre falls
exactly on the boundary of the region (a "tie-breaker" algorithm) and the
algorithm used to make the same sort of decisions in rasterizing a line.

To summarize these algorithms briefly, the algorithm used for filled regions
includes the same pixels as would be included if the boundary lines were to
be displaced an infinitesimal amount to the left (ignoring the special case
of horizontal lines). This is a simple, consistent model. The algorithm used
in line rasterization does not seem to be as well thought out - it seems to
have been chosen in an ad hoc fashion, with the only internal consistency
constraint being to make sure that the same pixels are hit independent of
the order in which the end points are specified.

For an example of the current line drawing, look at the diagrams below.
Here "*" indicates the specified end-points of the line, and "x" shows
the pixel that will be touched as part of the line drawing rasterization:

                        +---+---+       +---+---+
    +---+---+---+       | * |   |       |   | * |       +---+---+---+
    | * | x |   |       +---+---+       +---+---+       |   |   | * |
    +---+---+---+       | x |   |       | x |   |       +---+---+---+
    |   |   | * |       +---+---+       +---+---+       | * | x |   |
    +---+---+---+       |   | * |       | * |   |       +---+---+---+
                        +---+---+       +---+---+

It would be desirable for the tie-breaker algorithm used for line drawing
to be consistent with that used for defining interiors of filled regions.
If we apply the same decision procedure of imagining the line to be moved
an infinitesimal amount to the left we would want to draw lines as follows:

                        +---+---+       +---+---+
    +---+---+---+       | * |   |       |   | * |       +---+---+---+
    | * |   |   |       +---+---+       +---+---+       |   | x | * |
    +---+---+---+       | x |   |       | x |   |       +---+---+---+
    |   | x | * |       +---+---+       +---+---+       | * |   |   |
    +---+---+---+       |   | * |       | * |   |       +---+---+---+
                        +---+---+       +---+---+

Note that this only changes the rasterization of lines when the major axis
is the x-axis (and, of course, only for those pixels where we need to make
a choice between two equally close candidate pixels).

The pixels where we need to make a tie-breaker decision are those pixels
for which the Bresenham error term is exactly zero. The way to implement
this change is to change the code in the low-level Bresenham routines as
follows (using mfbbres.c as the example)

        if (axis == X_AXIS)
        {
	    if (signdx > 0)
	    {
          . . . .
		    if (e < 0)                  /* Change this to   if (e <= 0)  */
		        . . . .
		    else
          . . . .
	    }
	    else
	    {
          . . . .
		    if (e <= 0)                 /* Change this to   if (e < 0)   */
		        . . . .
		    else
          . . . .
	    }