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.