Graphics::drawHorizontalLine() broken on GIT head?

I suppose it could be that. Very odd, I’ve love to know exactly what’s going on.

OK, done some more digging. I checked the ellipsed drawing function and that renders fine using Core Graphics so perhaps it’s not a bug in my setup.

I tried some alternative ways of doing drawVerticalLine. It seems like many of the CG drawing functions don’t antialias unless it seems necessary in both the x and y directions, or something like that. To illustrate…

[code] void drawVerticalLine (const int x, double top, double bottom)
{
float lineTop = flipHeight - (float) bottom;
float lineHeight = (float) (bottom - top);

	CGContextBeginPath(context);
	CGContextMoveToPoint(context, x, lineTop);
	CGContextAddLineToPoint(context, x, lineTop+lineHeight);
	CGContextStrokePath(context);
}

[/code] does this (using some test code earlier in the thread): [attachment=2]using path integer x.png[/attachment]

So because of CG’s definition of pixel locations it antialiases in both directions (so looks grey rather than black and is antialiased at the left and right edges). So I figured offseting the x coord by 0.5 would work…

[code] void drawVerticalLine (const int x, double top, double bottom)
{
float lineTop = flipHeight - (float) bottom;
float lineHeight = (float) (bottom - top);
float floatX = x + 0.5f;

	CGContextBeginPath(context);
	CGContextMoveToPoint(context, floatX, lineTop);
	CGContextAddLineToPoint(context, floatX, lineTop+lineHeight);
	CGContextStrokePath(context);
}

[/code] Nope, it’s the same as before: [attachment=1]using path float x + 0.5.png[/attachment]

So if my assumption was correct how about confusing CG into antialiasing by offsetting by a little more than 0.5…

[code] void drawVerticalLine (const int x, double top, double bottom)
{
float lineTop = flipHeight - (float) bottom;
float lineHeight = (float) (bottom - top);
float floatX = x + 0.51f;

	CGContextBeginPath(context);
	CGContextMoveToPoint(context, floatX, lineTop);
	CGContextAddLineToPoint(context, floatX, lineTop+lineHeight);
	CGContextStrokePath(context);
}

[/code] Yep, that looks better: [attachment=0]using path float x + 0.51.png[/attachment]

But probably not ideal since it’s likely to be a lot slower than you’d expect drawVecticalLine to be and Juce’s software renderer could be faster, I guess. Anyway back to using CGContextFillRect to see if that can be confused into antialiasing by making the rectangle width very slightly larger than 1 pixel…

[code] void drawVerticalLine (const int x, double top, double bottom)
{
float rTop = flipHeight - (float) bottom;
float rHeight = (float) (bottom - top);

    CGContextFillRect (context, CGRectMake (x - 0.05, rTop, 1.05f, rHeight ));
}

[/code] Yes it can (trust me it looks almost identical to the last image but does have some minor antialiasing at the left - however I’m already up to 3 attachments).

I’m sure this is not the code you’d want to use but it shows at least what my system seems to be doing. Whether it’s the graphics card or Leopard, I don’t know.

This is the image for the last code fragment:[attachment=0]using rect slightly widened.png[/attachment]

Bloody hell. What a bunch of hackers…

Does this work?

CGContextFillRect (context, CGRectMake (x + 1.0f / 256.0f , rTop, 1.0f + 1.0f / 256.0f, rHeight ));

An offset of 1/256 shouldn’t affect the colour at all, so if that’s enough to trick it into rendering properly, it’d be a good workaround…

Yes that’s got it: [attachment=0]using rect very slightly widened.png[/attachment]

I’d hate to be slowing down everyone else if it’s a Leodard vs Snow Leopard issue. I’ll probably be upgrading to 10.6 v soon anyway so I can check.

It’d be good to find out if it’s leopard or your graphics card… Any other leopard users out there seen this? A quick way to check is to run the latest demo and try the vertical/horizontal line test on the graphics page.

Sorry to revisit this but my horizontal lines are now two pixels wide…

I’m sure I could provide a simpler example but I had this one as a test from the previous problem:

[code]class TestDrawHorizontalLine : public Component
{
public:
TestDrawHorizontalLine () { }
~TestDrawHorizontalLine () { }

void paint (Graphics& g) {
	g.fillAll(Colours::black);
	g.setColour(Colours::white);
	int height = getHeight();
	int width = getWidth();
	g.drawHorizontalLine(height/2, 0, width);
}	

};

class TestDrawLine : public Component
{
public:
TestDrawLine () { }
~TestDrawLine () { }

void paint (Graphics& g) {
	g.fillAll(Colours::black);
	g.setColour(Colours::white);
	int height = getHeight();
	int width = getWidth();
	g.drawLine(0, height/2, width, height/2);
}

};

class MainComponent : public Component
{
private:
TestDrawHorizontalLine *test1;
TestDrawLine *test2;

public:
MainComponent () {
addAndMakeVisible(test1 = new TestDrawHorizontalLine());
addAndMakeVisible(test2 = new TestDrawLine());
}

~MainComponent () {
	deleteAllChildren();
}

void resized () {
	test1->setBounds(20, 20, 200, 200);
	test2->setBounds(240, 20, 200, 200);
}

};[/code]

Does this: [attachment=0]Picture 2.png[/attachment]

Left is drawHorizontalLine() right is the same with drawLine(). Is it something to do with CoreGraphics’ pixels being referred to by their centre (i.e., at x + 0.5 and y + 0.5)?

However, drawVerticalLine() seems OK.

Strange - I don’t see that… Is this with coregraphics, or the software renderer?

It’s core graphics, - I had a quick play in the CG context but only made the line go grey rather than one pixel wide. I’ll have another play - I thought it might be something obvious…

Actually using the same code with the software renderer has a different problem:[attachment=1]Picture 3.png[/attachment]

I’m doing:

g.drawHorizontalLine(height/2, 0, width); g.drawVerticalLine(width/2, 0, height);

and

g.drawLine(0, height/2, width, height/2); g.drawLine(width/2, 0, width/2, height);

…respectively. The latter needs offseting by { 0.5f, 0.5f } to give: [attachment=0]Picture 4.png[/attachment]

…using:

g.drawLine(0, height/2 + 0.5f, width, height/2 + 0.5f); g.drawLine(width/2 + 0.5f, 0, width/2 + 0.5f, height);

But with the CG renderer the { 0.5f, 0.5f } needs removing to give the same result. Again this goes back to my suspicion that it’s something to do with CG pixel coords being referenced from their centre rather than their top-left.

Hmm - looks like I added a 0.5 cludge in there that is messing it up - no idea why I did that (probably to match the way the old rendering code used to work while I was developing the CG stuff), but I’ll remove it so that it matches the sw renderer coords.

Just wondering.
Is that supposed to be fixed ?

I’m seeing the blurry(antialiased) line with this the Juce Git tip on OSX using drawVerticalLine and drawHorizontalLine.
It works fine on Windows though.

Thanks,

Just wanted to mention that it doesn’t happen on all mac hardware.
Works fine(single line)on recent macbook pro but not on an old iMac (blurry)

Related to some optimization ?

Hope this helps.

Looking at the code.
I wanted to precise that the old mac target is 10.4 while other are on 10.6.
as I see some MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5

So maybe related to OSX version in fact

Hope this helps.

More test here.
Base SDK of 10.5 do not fix it.
It looks like that the issue is really related to the OS runnnig.
10.5 versus 10.6