# Fast line drawing

In the project I’m working on, I need a lot (hundreds) of lines of variable thickness to be drawn on the screen. I noticed that the painting becomes excessively slow when using Graphics::drawLine(). I managed to write some code that is exactly 10x (!) faster than JUCE’s drawLine() function, but which has 3 drawbacks:

1. the line thickness is actually always twice than the thickness parameter I am passing
2. the ends of the lines are not properly drawn like in JUCE
3. it seems that the lines’ visual thickness changes a bit when the angle changes.

Jules, would it be possible to create a faster drawLine() function in JUCE? Right now you’re creating a Path and filling it, but I’m sure it can be done much faster.

Anyway, for reference, here’s my code:

[code]// for lineThickness, pass a value that is HALF of the actual thickness
void MyRenderer::drawLineFast(int x0, int y0, int x1, int y1, int lineThickness)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;

``````int j1=1-lineThickness;
int j2=lineThickness;

if (dx>=dy)
{
float y=float(y0);
while (x0!=x1)
{
x0+=sx;
int iY=int(y);

float k=y-float(iY);

blendPixelInternal2(x0, iY+j1-1, alpha*(1.0f-k));
for (int j=j1; j<j2; j++)
blendPixelInternal2(x0, iY+j, alpha);
blendPixelInternal2(x0, iY+j2, alpha*k);
}
}
else
{
float x=float(x0);
while (y0!=y1)
{
y0+=sy;
int iX=int(x);
float k=x-float(iX);
blendPixelInternal2(iX+j1-1, y0, alpha*(1.0f-k));
for (int j=j1; j<j2; j++)
blendPixelInternal2(iX+j, y0, alpha);
blendPixelInternal2(iX+j2, y0, alpha*k);
}
}
``````

}

void MYRenderer::blendPixelInternal2(int x0, int y0, uint8 alpha_)
{
if (x0>=clipLeft && x0<clipRight && y0>=clipTop && y0<clipBottom)
{
uint8 data = buf+ x0pixelStride + y0*lineStride;
uint8 b_=255-alpha_;
data[0]=((uint16(data[0])b_+balpha_)>>8);
data[1]=((uint16(data[1])b_+galpha_)>>8);
data[2]=((uint16(data[2])b_+ralpha_)>>8);
}
}[/code]

``````
If alpha_ == 255 and b == 255 you get

( 255 *255 ) / 256 = 254

You're getting 254 instead of the correct value 255 (output = input). Although this might not matter for your purposes.

Since you're looking for performance it is possible to replace a multiply with a subtraction:

[code]
data[0] + (((b - data[0]) * alpha) >> 8)
[/code]``````

If alpha_ == 255 and b == 255 you get

( 255 *255 ) / 256 = 254

You’re getting 254 instead of the correct value 255 (output = input). Although this might not matter for your purposes.

Since you’re looking for performance it is possible to replace a multiply with a subtraction:

``data[0] + (((b - data[0]) * alpha) >> 8)``

Yeah, in the old days I used to have a non-path based line drawing method, but the inaccuracies at the ends caused problems. It was also important to make sure that the line-drawing looks the same on all platforms (e.g. pixel-for-pixel equivalent to CoreGraphics and other toolkits)

If you can come up with a faster algorithm that produces exactly the same output as the existing method, then that’d be great! But it’d need to be a replacement for the existing method - there’s no way I’d agree to bloat the class with extra methods like “drawLineFast”. (It’d also have to cope with gradient and image fills!)