The most obvious way to generate styled lines is to draw a circle at the origin, and then draw a dashed line from the origin to all points on the circle. The number of dashes in each line will be the same and the lengths of all the dashes drawn will be equal. This is executed on microcode on some devices. However, it is too costly in terms of processor time to implement it in software. Therefore, an alternative method called the "maximum metric" is used in the graphics engine. This method can be visualized by drawing a square centered at the origin, and then drawing a dashed line to any point on the square. The number of dashes in each line will be the same but the lengths of the dashes will vary.

The maximum metric states that:

{y-major = ABS(y1-y0) > ABS(x1-x0)
where (x0, y0) and (x1, y1) are the endpoints of the line in
device-coordinate space},
add pDC -> usStyleRatioY to error-term value upon each
increment of Y as the line is drawn

{x-major = ABS(x1-x0) > ABS(y1-y0) in device-coordinate space},
add pDC -> usStyleRatioX to error-term value upon each increment
of X as line is drawn

The line style as viewed on the device is determined, as follows:

if (ABS(pDC -> usStyleRatioX * sDeltaX) > ABS(pDC -> usStyleRatioY * sDeltaY))
    LineStyleAsItLooksOnTheDevice = X-MAJOR;
else
    LineStyleAsItLooksOnTheDevice = Y-MAJOR;

This might be coded similar to the following:

if (ABS(pDC -> usStyleRatioX * sDeltaX) > ABS(pDC -> usStyleRatioY * sDeltaY)) {
    usChangeInStateForOnePixel = pDC -> usStyleRatioX; fAddThisWhen = X_INCREMENTS;
} else {
        usChangeInStateForOnePixel = pDC -> usStyleRatioY; fAddThisWhen = Y_INCREMENTS;
}

It follows that for a line (AB), the total change in style state can be expressed as:

usChangeInStateForWholeLine = MAX(ABS(pDC -> usStyleRatioX * sDeltaX),
                              ABS(pDC -> usStyleRatioY * sDeltaY))
where sDeltaX = Bx-Ax and sDeltaY = By-Ay

For example, an EGA device that has a 640 x 350 (X-to-Y) resolution is displayed on a display that has an X-to-Y ratio of 1-to-.75. To calculate the aspect ratio:

X/Y Ratio = 350/(640*.75) = .72917   Therefore: X = Y*.72917 or Y = X/.72917

This indicates that a pel is taller than it is wide. The following figure visually describes the ratio.

Pel Aspect Ratio

Assume that four pels in the X-direction is the desirable size of a styled-line dot. Because this display is 9.5 inches across and there are 640 pels across, the length of the four pels is:

(9.5inches/640pels) * 4pels = .059375inches
This results in a pDC -> usStyleRatioX = 64&:
                                    64 = 256/4

Note that 256 = 0x100, which corresponds to an overflow of the error-term byte into the mask position. To get the equivalent pDC  usStyleRatioY value, use the desired distance and multiply it by Y pels per inch, as follows:

(.059375inches * 350 pels)/7.125inches = 2.917pels
Therefore:pDC  usStyleRatioY = 256/2.917 = 87.76 (rounded to 88)

An easier method is to calculate pDC  usStyleRatioY from pDC  usStyleRatioX, using the following aspect ratio:

pDC  usStyleRatioY = pDC  usStyleRatioX / .72917 = 87.76 (rounded to 88)

Note that the values pDC  usStyleRatioX and pDC  usStyleRatioY are the same as those returned by GreGetStyleRatio.

An example of what is meant by "as viewed on the device" follows:

If a line is drawn from (0, 0) to (100, 100) pels on the device, it is
drawn as a diagonal line but does not look diagonal to an observer.
Instead, it looks like a line drawn to (100, 73).

This change of perspective is because of the aspect ratio. Each unit
(pel) in the X-direction covers only .72917 as much distance as a pel
in the Y-direction. The images on the device do not look skewed
because this ratio is factored in when the application draws a diagonal
line (for example, by drawing from (0, 0) to (73, 100)).

The styled lines are affected when a line that is drawn in pels as
X-major appears on the device as Y-major. In this case, a line drawn
from (0, 0) to (85, 64) is X-major as drawn in pels
(because ABS(x1-x0) > ABS(y1-y0)), but appears on the device to be
Y-major. Notice that this line must be styled Y-major to look correct on
the device, as follows:

usChangeInStateForOnePixel = ABS(pDC -> usStyleRatioX * sDeltaX) > ABS(pDC -> usStyleRatioY
                             * sDeltaY)?
                             pDC -> usStyleRatioX :pDC -> usStyleRatioY;
where:
     ABS(pDC -> usStyleRatioX * sDeltaX) = 64 * 85 = 5440
     ABS(pDC -> usStyleRatioY * sDeltaY) = 88 * 64 = 5632

Because 5440 < 5632, the line is styled Y-major by using
pDC  usStyleRatioY. The X-major diagonal line drawing routine
usually adds pDC  usStyleRatioX to the error-term byte for every
increment of X. This is correct if the aspect ratio is 1:1.

However, because the aspect ratio is not 1:1, pDC 
usStyleRatioY must be used in this case for every increment of Y,
although the line is drawn as an X-major line with the X-major routine.
This means that regardless of which way the line is drawn, it must be
styled according to how it looks on the device, which is determined by
the maximum metric method described previously.

LINETYPE_ALTERNATE is a special case of styled line. When drawing a line of this type (pLbnd  usType = LINETYPE_ALTERNATE), the X and Y style ratios are temporarily set to 256 to set every other pel on the line ON. Notice that changing the values returned by GreGetStyleRatio is not necessary because the graphics engine does not call this function if the line type is LINETYPE_ALTERNATE.


[Back: Line Functions]
[Next: PolyShortLines and Styling]