and this ...
The assembly one was around twice as fast btw.
///////////////////////////////////////////////// // LINEC2.CPP (c) 11/11/1997 Jake Birkett ///////////////////////////////////////////////// // C implementation of Bresenham's Line Algorithm // using Run Sliced technology // // External Functions : /////////////////////// // void LineC2(void); // // External Variables : /////////////////////// // unsigned int lx1 = 0; // line start x coord // unsigned int ly1 = 0; // unsigned int lx2 = 0; // line end y coord // unsigned int ly2 = 0; // // unsigned char far *line_dest; // unsigned char line_colour; // 0-255 ///////////////////////////////////////////////// // I N C L U D E S ////////////////////////////// ///////////////////////////////////////////////// #include "linec2.h" #include <stdlib.h> ///////////////////////////////////////////////// // D E F I N E S //////////////////////////////// ///////////////////////////////////////////////// ///////////////////////////////////////////////// // P R O T O T Y P E S ////////////////////////// ///////////////////////////////////////////////// // INTERNAL void Line_H_Run(int length); // draws a horizontal run of pixels void Line_V_Run(int length); // draws a vertival run of pixels // EXTERNAL void LineC2(void); ///////////////////////////////////////////////// // G L O B A L S //////////////////////////////// ///////////////////////////////////////////////// // INTERNAL int i = 0; // used in for loops int index16 = 0; // used in Run Loops int ldx = 0; // delta x of line int ldy = 0; // delta y of line int adj_up = 0; // error term increment int adj_down = 0; // error term decrement int error_term = 0; // line error value int x_inc = 0; // x direction ... -1 = left ; 1 = right int y_inc = 0; int whole_step; // minimum number of pixels in a run ... DeltaX/DeltaY int pc_initial; // pixel count initial ... 1st run int pc_final; // pixel count final ... last run int run_length; // length of run to be drawn unsigned char far *vb_pixel; // pointer to destination pixel // EXTERNAL unsigned int lx1 = 0; // line start x coord unsigned int ly1 = 0; unsigned int lx2 = 0; // line end y coord unsigned int ly2 = 0; unsigned char far *line_dest=(unsigned char far *)0xA0000000L; // default destination if video buffer unsigned char line_colour; // 0-255 ///////////////////////////////////////////////// // F U N C T I O N S //////////////////////////// ///////////////////////////////////////////////// void LineC2(void) { // Draws a line using Bresenham's Line Algorithm onto the // video buffer or alternate destination specified by line_dest. // Uses Run Sliced technology // calc starting pixel vb_pixel = line_dest + (ly1*320) + lx1; // compute deltas ldx = lx2-lx1; ldy = ly2-ly1; // calc vertical direction ... up or down if (ldy<0) { y_inc = -320; ldy = 0-ldy; } else y_inc = 320; // calc horizontal direction ... -1 = left ; 1 = right if (ldx<0) { x_inc = -1; ldx = 0-ldx; // make DeltaX positive } else x_inc = 1; // Special Case : Vertical Line if (ldx==0) // no x movement { for (i=0; i<=ldy; i++) { *vb_pixel = line_colour; vb_pixel += y_inc; } return; } // Special Case : Horizontal Line if (ldy==0) // no y movement { for (i=0; i<=ldx; i++) { *vb_pixel = line_colour; vb_pixel += x_inc; } return; } // Special Case : Diagonal Line if (ldx==ldy) { for (i=0; i<=ldx; i++) { *vb_pixel = line_colour; vb_pixel += y_inc + x_inc; } return; } // find out if line is X Major or Y Major if (ldx>=ldy) { // X Major whole_step = ldx/ldy; // minimum number of pixels in a run adj_up = (ldx%ldy)*2; // % = remainder of division adj_down = ldy*2; // DeltaY*2 error_term = (ldx%ldy) - adj_down; // initial error term at half a pixel // Calc lengths of initial and final partial runs // because Y advances on 0.5 pixels for these runs. // Divide 1 full run + initial pixel between the first_last runs. pc_initial = (whole_step/2) + 1; pc_final = pc_initial; // If the basic run length is even and there is no fractional advance // we have 1 pixel too many which will be taken away from pc_initial if ((adj_up==0)&&((whole_step&0x01)==0)) pc_initial --; // If there is an odd number of pixels per run, meaning // we must adjust the error term by 0.5 .. half a pixel if ((whole_step&0x01)!=0) error_term += ldy; Line_H_Run(pc_initial); // draw initial run for (i=0; i<ldy-1; i++) { run_length = whole_step; // set run length to minimum run length if ((error_term += adj_up) > 0) // advance error term and test it { run_length++; error_term -= adj_down; // bring error term back down } Line_H_Run(run_length); // draw this scan lines run } Line_H_Run(pc_final); // draw final run return; } else { // Y Major whole_step = ldy/ldx; // minimum number of pixels in a run adj_up = (ldy%ldx)*2; // % = remainder of division adj_down = ldx*2; // DeltaY*2 error_term = (ldy%ldx) - adj_down; // initial error term at half a pixel // Calc lengths of initial and final partial runs // because X advances on 0.5 pixels for these runs. // Divide 1 full run + initial pixel between the first_last runs. pc_initial = (whole_step/2) + 1; pc_final = pc_initial; // If the basic run length is even and there is no fractional advance // we have 1 pixel too many which will be taken away from pc_initial if ((adj_up==0)&&((whole_step&0x01)==0)) pc_initial --; // If there is an odd number of pixels per run, meaning // we must adjust the error term by 0.5 .. half a pixel if ((whole_step&0x01)!=0) error_term += ldx; Line_V_Run(pc_initial); // draw initial run for (i=0; i<ldx-1; i++) { run_length = whole_step; // set run length to minimum run length if ((error_term += adj_up) > 0) // advance error term and test it { run_length++; error_term -= adj_down; // bring error term back down } Line_V_Run(run_length); // draw this scan lines run } Line_V_Run(pc_final); // draw final run return; } } // end LineC2 ///////////////////////////// void Line_H_Run(int length) { // draws a horizontal run of pixels for (index16=0; index16<length; index16++) { *vb_pixel = line_colour; vb_pixel += x_inc; } vb_pixel += y_inc; // point to next scan line down } // end Line_H_Run ///////////////////////////// void Line_V_Run(int length) { for (index16=0; index16<length; index16++) { *vb_pixel = line_colour; vb_pixel += y_inc; } vb_pixel += x_inc; // point to next scan line down } // end Line_V_Run /////////////////////////////////////////////////
The assembly one was around twice as fast btw.