Replace invalid characters with HTML entities
— with — ’ with ’ + with + × with x ç with ç “ with “ ” with ” ‘ with ‘ • with • – with - µ with µ † with † Fix C++ θ with θ Yen symbol instead of times Fix broken apos Bullet again E-circumflex
This commit is contained in:
parent
9e52de9586
commit
500e7f5654
353 changed files with 5091 additions and 5091 deletions
56
39-03.html
56
39-03.html
|
|
@ -36,21 +36,21 @@
|
|||
</TABLE>
|
||||
</CENTER>
|
||||
<P><BR></P>
|
||||
<P>Listing 39.2 shows a C implementation of integer edge tracing. Vertical and diagonal lines, which are trivial to trace, are special-cased. Other lines are broken into two categories: Y-major (closer to vertical) and X-major (closer to horizontal). The handlers for the Y-major and X-major cases operate on the principle of similar triangles: The number of X pixels advanced per scan line is the same as the ratio of the X delta of the edge to the Y delta. Listing 39.2 is more complex than the original floating point implementation, but not painfully so. In return for that complexity, Listing 39.2 is more than 80 times faster at scanning edges—and, as just mentioned, it’s actually more accurate than the floating point code.
|
||||
<P>Listing 39.2 shows a C implementation of integer edge tracing. Vertical and diagonal lines, which are trivial to trace, are special-cased. Other lines are broken into two categories: Y-major (closer to vertical) and X-major (closer to horizontal). The handlers for the Y-major and X-major cases operate on the principle of similar triangles: The number of X pixels advanced per scan line is the same as the ratio of the X delta of the edge to the Y delta. Listing 39.2 is more complex than the original floating point implementation, but not painfully so. In return for that complexity, Listing 39.2 is more than 80 times faster at scanning edges—and, as just mentioned, it’s actually more accurate than the floating point code.
|
||||
</P>
|
||||
<P>Ya gotta love that integer arithmetic.</P>
|
||||
<P><B>LISTING 39.2 L39-2.C</B></P>
|
||||
<!-- CODE //-->
|
||||
<PRE>
|
||||
/* Scan converts an edge from (X1,Y1) to (X2,Y2), not including the
|
||||
point at (X2,Y2). If SkipFirst == 1, the point at (X1,Y1) isn’t
|
||||
point at (X2,Y2). If SkipFirst == 1, the point at (X1,Y1) isn’t
|
||||
drawn; if SkipFirst == 0, it is. For each scan line, the pixel
|
||||
closest to the scanned edge without being to the left of the
|
||||
scanned edge is chosen. Uses an all-integer approach for speed and
|
||||
precision. */
|
||||
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
#include “polygon.h”
|
||||
|
||||
void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
||||
int SkipFirst, struct HLine **EdgePointPtr)
|
||||
|
|
@ -74,7 +74,7 @@ void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
|||
/* The edge is vertical; special-case by just storing the same
|
||||
X coordinate for every scan line */
|
||||
/* Scan the edge for each scan line in turn */
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
/* Store the X coordinate in the appropriate edge list */
|
||||
if (SetXStart == 1)
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
|
|
@ -85,39 +85,39 @@ void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
|||
/* The edge is diagonal; special-case by advancing the X
|
||||
coordinate 1 pixel for each scan line */
|
||||
if (SkipFirst) /* skip the first point if so indicated */
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
/* Scan the edge for each scan line in turn */
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
/* Store the X coordinate in the appropriate edge list */
|
||||
if (SetXStart == 1)
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
else
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
}
|
||||
} else if (Height > Width) {
|
||||
/* Edge is closer to vertical than horizontal (Y-major) */
|
||||
if (DeltaX >= 0)
|
||||
ErrorTerm = 0; /* initial error term going left->right */
|
||||
else
|
||||
ErrorTerm = -Height + 1; /* going right->left */
|
||||
ErrorTerm = -Height + 1; /* going right->left */
|
||||
if (SkipFirst) { /* skip the first point if so indicated */
|
||||
/* Determine whether it’s time for the X coord to advance */
|
||||
if ((ErrorTerm += Width) > 0) {
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
/* Determine whether it’s time for the X coord to advance */
|
||||
if ((ErrorTerm += Width) > 0) {
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
ErrorTerm -= Height; /* advance ErrorTerm to next point */
|
||||
}
|
||||
}
|
||||
/* Scan the edge for each scan line in turn */
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
/* Store the X coordinate in the appropriate edge list */
|
||||
if (SetXStart == 1)
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
else
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
/* Determine whether it’s time for the X coord to advance */
|
||||
if ((ErrorTerm += Width) > 0) {
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
/* Determine whether it’s time for the X coord to advance */
|
||||
if ((ErrorTerm += Width) > 0) {
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
|
||||
}
|
||||
}
|
||||
|
|
@ -130,38 +130,38 @@ void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
|||
if (DeltaX >= 0)
|
||||
ErrorTerm = 0; /* initial error term going left->right */
|
||||
else
|
||||
ErrorTerm = -Height + 1; /* going right->left */
|
||||
ErrorTerm = -Height + 1; /* going right->left */
|
||||
if (SkipFirst) { /* skip the first point if so indicated */
|
||||
X1 += XMajorAdvanceAmt; /* move X minimum distance */
|
||||
/* Determine whether it’s time for X to advance one extra */
|
||||
if ((ErrorTerm += ErrorTermAdvance) > 0) {
|
||||
X1 += AdvanceAmt; /* move X one more */
|
||||
X1 += XMajorAdvanceAmt; /* move X minimum distance */
|
||||
/* Determine whether it’s time for X to advance one extra */
|
||||
if ((ErrorTerm += ErrorTermAdvance) > 0) {
|
||||
X1 += AdvanceAmt; /* move X one more */
|
||||
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
|
||||
}
|
||||
}
|
||||
/* Scan the edge for each scan line in turn */
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
/* Store the X coordinate in the appropriate edge list */
|
||||
if (SetXStart == 1)
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
else
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
X1 += XMajorAdvanceAmt; /* move X minimum distance */
|
||||
/* Determine whether it’s time for X to advance one extra */
|
||||
if ((ErrorTerm += ErrorTermAdvance) > 0) {
|
||||
X1 += AdvanceAmt; /* move X one more */
|
||||
X1 += XMajorAdvanceAmt; /* move X minimum distance */
|
||||
/* Determine whether it’s time for X to advance one extra */
|
||||
if ((ErrorTerm += ErrorTermAdvance) > 0) {
|
||||
X1 += AdvanceAmt; /* move X one more */
|
||||
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*EdgePointPtr = WorkingEdgePointPtr; /* advance caller’s ptr */
|
||||
*EdgePointPtr = WorkingEdgePointPtr; /* advance caller’s ptr */
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
<H3><A NAME="Heading6"></A><FONT COLOR="#000077">The Finishing Touch: Assembly Language</FONT></H3>
|
||||
<P>The C implementation in Listing 39.2 is now nearly 20 times as fast as the original, which is good enough for most purposes. Still, it requires that one of the large data models be used (for <B>memset</B> ), and it’s certainly not the fastest possible code. The obvious next step is assembly language.</P>
|
||||
<P>Listing 39.3 is an assembly language version of <B>DrawHorizontalLineList</B> . In actual use, it proved to be about 36 percent faster than Listing 39.1; better than a poke in the eye with a sharp stick, but just barely. There’s more to these timing results than meets that eye, though. Display memory generally responds much more slowly than system memory, especially in 386 and 486 systems. That means that much of the time taken by Listing 39.3 is actually spent waiting for display memory accesses to complete, with the processor forced to idle by wait states. If, instead, Listing 39.3 drew to a local buffer in system memory or to a particularly fast VGA, the assembly implementation might well display a far more substantial advantage over the C code.</P><P><BR></P>
|
||||
<P>The C implementation in Listing 39.2 is now nearly 20 times as fast as the original, which is good enough for most purposes. Still, it requires that one of the large data models be used (for <B>memset</B> ), and it’s certainly not the fastest possible code. The obvious next step is assembly language.</P>
|
||||
<P>Listing 39.3 is an assembly language version of <B>DrawHorizontalLineList</B> . In actual use, it proved to be about 36 percent faster than Listing 39.1; better than a poke in the eye with a sharp stick, but just barely. There’s more to these timing results than meets that eye, though. Display memory generally responds much more slowly than system memory, especially in 386 and 486 systems. That means that much of the time taken by Listing 39.3 is actually spent waiting for display memory accesses to complete, with the processor forced to idle by wait states. If, instead, Listing 39.3 drew to a local buffer in system memory or to a particularly fast VGA, the assembly implementation might well display a far more substantial advantage over the C code.</P><P><BR></P>
|
||||
<CENTER>
|
||||
<TABLE BORDER>
|
||||
<TR>
|
||||
|
|
|
|||
Loading…
Reference in a new issue