Microsoft Windows CE 3.0  

The EmulatedLine Function

Important:
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

EmulatedLineis the GPE default line-drawing function. The following code example shows the algorithm EmulatedLineuses.

long accum = (long)(pParms->dN) +
pParms->llGamma; long axstp = (long)(pParms->dN); long dgstp
= (long)(pParms->dN) - (long)(pParms->dM); for( remainingPels
= pParms->cPels; remainingPels; remainingPels-- ) { if( accum
< 0) { accum += axstp; } else { increment_in_minor_direction;
accum += dgstp; } } increment_in_major_direction;
draw_current_pixel; }

You should use EmulatedLineto handle diagonal lines, which are relatively rare and therefore usually do not need to be accelerated. Similarly, it is quite rare for line styles to be used. EmulatedLineshould be used as the default processor for this case as well.

For devices that support hardware line-drawing acceleration, the driver can implement its own accelerated line function to replace the default EmulatedLineimplementation. Alternatively, the driver can call an existing emulation function or create a new software emulation function to handle the line drawing. Even if adequate line-drawing acceleration is available, if solid-fill block transfer (BLT) acceleration is implemented in the hardware, this should be used to accelerate horizontal and vertical lines, since hardware-accelerated BLT operations are almost always faster than hardware accelerated line operations.

The recommended approach for most situations is to emulate all diagonal and styled lines, and to use either line-drawing hardware or fill-BLT hardware to accelerate horizontal and vertical lines. Horizontal and vertical lines comprise the majority of lines drawn by Windows CE, so this approach gives good results.

For horizontal and vertical lines, dNwill be zero and no account need be taken of the subpixel information in dMand error term llgamma, as shown in the following code example.

if( pLineParms->dN == 0 ) { //Line is vertical
or horizontal //Use fill-BLGT or h/w line to draw a line starting
at //pLineParms->xStart, pLineParms->yStart //in the
direction specified by pLineParms->iDir //for a total of
pLineParms->cPels pixels } else // use software implementation
for diagonal lines { return EmulatedLine( pLineParms ); }

For diagonal lines, the values in the dM, dN, and error term llgammafields of GPELineParms contain subpixel information. This information should be used when initializing hardware line-drawing registers, otherwise diagonal lines that are clipped will be incorrectly drawn. This effect can be quite noticeable when moving a window over another window that contains a diagonal line.

In the prepare phase, the driver performs a general inspection of the line parameters to determine whether it can accelerate the line. When the acceleration function is called, the driver might need to perform additional validation. This is because when the driver's accelerated function is called, it will be for a specific path segment clipped to a specific clipping region. The driver must ensure that the line segment length will not cause its hardware registers to overflow.

The sample code below shows how to make these additional checks. Because the dMand dNvalues are originally expressed in 1/16ths of a pixel, the hardware slope iterators of the device must be able to retain these lengths for whatever line segment is being drawn. A lot of hardware is designed to be able to draw a diagonal line across the whole screen, but this hardware expects the dM, dNvalues (or equivalents) to be expressed in pixels. Because GPE uses subpixel precision, these counters need 4 more bits. For short lines, this is not a problem. However, for long lines, these values can overflow the registers and cause the hardware to draw incorrect lines.

While diagonal lines are uncommon, long diagonal lines are extremely rare, so the time taken to render long diagonal lines using the EmulatedLinefunction is unimportant. The following code sample shows one way to check the line parameters to ensure that they will not overflow the hardware registers.

Int errTerm = (in)pLineParms->dN +
(in)pLineParms->llGamma – ( ( command & PLUS_X ) ? 0 " 1 );
if( ( pLineParms->dN > 4090 || //Remember dM >= dN (
errTerm > 4090 ) || ( errTerm < -4090 ) ) { RetVal =
EmulatedLine(pLineParms); //The hardware DDA would //overflow; use
emulation. } else { WaitForFIFO(7); //seven parameters required
reg_ALT_CURXY = ((pLineParms->xStart + ((S3Trio64Surf*)
(pLineParms->pDst))->Left()) << 16 |
(pLineParms->yStart + ((S3Trio64Surf*)
(pLineParms->pDst))->Top()); reg_MAJ_AXIS_PCNT =
(pLineParms->cPels-1); reg_ALT_STEP =
(((pLineParms->dN-pLineParms->dN)/*&0x3FFF*/)<<16)
| (pLineParms->dN /*&0x3FFF*/); reg_err_Term = errTerm
/*&0x3FFF*/; reg_CMD = command; RetVal = S_OK; }


 Last updated on Tuesday, July 13, 2004

© 2004 Microsoft Corporation. All rights reserved.