Here is a complete source which seems to work for me, with the VCL (Embarcadero). I put the modifications below to fix a problem on long lines which made position errors on x1,y1 drawing (pb discovered by comparing with a standard Bresenham line, MoveTo() and LineTo):
- Change the variables type from 'int' to 'float',
- Casting 'dy' value to int, in the loops.
Some Lambdas where also added, and C++ types for 32 and 8 bit are used.
Tests of speed have not been done (double
is sometimes faster than float
).
The speed is ok for me, as I work in a bitmap buffer; this needs to be done, because drawing directly on a component is too slow, as opposed to memory drawing (pC below is a pointer to a bitmap canvas). Then, all the bitmap is transfered in the paintbox.
Thanks to the contributors, @giogix and @Spektre.
void aaLine(int x0, int y0, int x1, int y1, int col)
{
auto pnt = [&](int x, int y, uint32_t c){
pC->Pixels[x][y] = static_cast<TColor>(c);
};//-----------------------------
auto pix_color = [&](uint32_t x, uint32_t y){
return pC->Pixels[x][y];
};//-----------------------------
float x, y, dx, dy, kx, ky, f, df;//Changed 'int' into 'float' to avoid error on x1,y1 drawing
uint32_t a,a0;
union {
uint32_t dd;
BYTE db[4];
} c,c0;
auto mix_colors = [&](){
c.db[0]= uint32_t(( uint32_t(c.db[0])*a + uint32_t(c0.db[0])*a0)>>8);
c.db[1]= uint32_t(( uint32_t(c.db[1])*a + uint32_t(c0.db[1])*a0)>>8);
c.db[2]= uint32_t(( uint32_t(c.db[2])*a + uint32_t(c0.db[2])*a0)>>8);
};
dx=x1-x0; kx=0; if (dx>0) kx=+1; else if (dx<0) { kx=-1; dx=-dx; }
dy=y1-y0; ky=0; if (dy>0) ky=+1; else if (dy<0) { ky=-1; dy=-dy; }
if (dx+dy==0) {
pnt(x0,y0,col);
pnt(x1,y1,col);
return;
}
if (dx>=dy)
for (df=(int(dy)<<8)/dx, x=x0, y=y0, f=0; ; f+=df, x+=kx) //Put int(dy)
{
// fixed point y step
if (f>=256) { f-=256; y+=ky; }
// line color + background color mixing
c.dd=col; c0.dd=pix_color(x,y); a=256-f; a0=f;
mix_colors();
pnt(x,y ,c.dd);
// line color + background color mixing
c.dd=col; c0.dd=pix_color(x,y+ky); a=f; a0=256-f;
mix_colors();
pnt(x,y+ky,c.dd);
if (x==x1) break;
}
else
for (df=(int(dx)<<8)/dy, x=x0, y=y0, f=0; ; f+=df, y+=ky) //Put int(dx)
{
// fixed point x step
if (f>=256) { f-=256; x+=kx; }
// line color + background color mixing
c.dd=col; c0.dd=pix_color(x,y); a=256-f; a0=f;
mix_colors();
pnt(x,y ,c.dd);
// line color + background color mixing
c.dd=col; c0.dd=pix_color(x+kx,y); a=f; a0=256-f;
mix_colors();
pnt(x+kx,y,c.dd);
if (y==y1) break;
}
}