The Allegro Wiki is migrating to github at https://github.com/liballeg/allegro_wiki/wiki

# NewAPI/Primitives/al draw line

This shall be the software equivalent to the OpenGL line calls. Aside from the solid colour line, a shaded line is also planned. AA is theorized for the far future.

Goals

- Match the OpenGL spec, since the GPU people have no consensus on what the lines should look like. See: Diamond Exit Rule
- Be able to use the lines to outline triangles in an easy fashion-
**Done**

Problems so far

- Lines joined end to end sometimes have overdraw or gaps, need a better start/end point classifier. For now, there is a modified diamond-exit rule implemented, but it is not very good. I doubt that overdraw can be eliminated, so I am focusing on eliminating the gaps instead.

Status

- We can't have both with a single function from what I understand - either a single line has both end points, or we have no overdraw when you attach multiple lines. OpenGL does the latter, i.e. there never is overdraw (or gaps) if you join lines. Not sure what we should do for al_draw_line really. Right now it follows OpenGL when using non-software drivers, i.e. the last pixel is always missing. Probably half of the time that is what one would expect (especially when coming from A4) - half of the time it's not. --Elias 02:21, October 15, 2008 (MDT)
- I've determined that it is not possible to eliminate gaps/overdraw in the general case, so I decided to have it operate as follows:
- Given a line strip, the very last pixel of the line strip will not be drawn
- Inside the line strip, there will be no overlap for most combinations of lines - this will be taken care of by an internal mechanism

- The implication is that if you have two line strips composed each of one line end to end, they might have gaps/overdraw. However, if you have a single line strip composed of those two lines, most reasonable combinations won't have gaps. I feel that this is a reasonable compromise, and really the only thing I can do. SiegeLord 15:48, October 17, 2008 (MDT)

- I've determined that it is not possible to eliminate gaps/overdraw in the general case, so I decided to have it operate as follows:

- Trying to fix the above

A4 test code:

<highlightSyntax language="cpp"> void al_draw_line3(BITMAP* bmp, float x1, float y1, float x2, float y2, int color) { if(y2 < y1) { float t; t = y2; y2 = y1; y1 = t;

t = x2; x2 = x1; x1 = t; }

const float dx = x2 - x1; const float dy = y2 - y1;

const int end_x = floorf(x2 + 0.5f); const int end_y = floorf(y2 + 0.5f);

#define FIRSTCHECK (x2 - x1) * ((float)x - x1) + (y2 - y1) * ((float)y - y1) >= 0 #define LASTCHECK (x1 - x2) * ((float)x - x2) + (y1 - y2) * ((float)y - y2) > 0

#define WORKER(var1, var2, comp, dvar1, dvar2, derr1, derr2, draw) \ { \ if(err comp) \ { \ var1 += dvar1; \ err += derr1; \ } \ \ if(draw) tester(bmp, x, y, color); \ \ var2 += dvar2; \ err += derr2; \ }

if(dx > 0) { if(dx > dy) { int x = floorf(x1 + 0.5f); int y = floorf(y1);

float err = (y1 - float(y)) * dx - (x1 - float(x)) * dy;

if(x < end_x) { WORKER(y, x, > 0.5f * dx, 1, 1, -dx, dy, FIRSTCHECK) }

while(x < end_x) { WORKER(y, x, > 0.5f * dx, 1, 1, -dx, dy, 1) }

if(x <= end_x) { WORKER(y, x, > 0.5f * dx, 1, 1, -dx, dy, LASTCHECK) } } else { int x = floorf(x1); int y = floorf(y1 + 0.5f);

float err = (x1 - float(x)) * dy - (y1 - float(y)) * dx;

if(y < end_y) { WORKER(x, y, > 0.5f * dy, 1, 1, -dy, dx, FIRSTCHECK) }

while(y < end_y) { WORKER(x, y, > 0.5f * dy, 1, 1, -dy, dx, 1) }

if(y <= end_y) { WORKER(x, y, > 0.5f * dy, 1, 1, -dy, dx, LASTCHECK) } } } else { if(-dx > dy) { int x = floorf(x1 + 0.5f); int y = floorf(y1);

float err = (y1 - float(y)) * dx - (x1 - float(x)) * dy;

if(x > end_x) { WORKER(y, x, <= 0.5f * dx, 1, -1, -dx, -dy, FIRSTCHECK) }

while(x > end_x) { WORKER(y, x, <= 0.5f * dx, 1, -1, -dx, -dy, 1) }

if(x >= end_x) { WORKER(y, x, <= 0.5f * dx, 1, -1, -dx, -dy, LASTCHECK) } } else { int x = floorf(x1); int y = floorf(y1 + 0.5f);

float err = (x1 - float(x)) * dy - (y1 - float(y)) * dx;

/* This is the only correction that needs to be made in the opposite direction of dy (or dx) */ if(err > 0.5f * dy) { x += 1; err -= dy; }

if(y < end_y) { WORKER(x, y, <= -0.5f * dy, -1, 1, dy, dx, FIRSTCHECK) }

while(y < end_y) { WORKER(x, y, <= -0.5f * dy, -1, 1, dy, dx, 1) }

if(y <= end_y) { WORKER(x, y, <= -0.5f * dy, -1, 1, dy, dx, LASTCHECK) } } } #undef FIRSTCHECK #undef LASTCHECK #undef WORKER } </highlightSyntax>