iOS 12 line drawing bug

Hi Folks,

Just found and worked-around a Juce / iOS 12 line drawing bug. I’m letting you know ASAP in case it helps.

NB all is fine on iOS 11.x - issue shown below occurs on both iPhone and iPad.

Before fix (shows the issue)

After fix (no longer shows the issue)

The line of code in my app that needed to change:
g.drawLine((float)lBarX, 0, (float)lBarX, (float)lHeight-1);

I fixed the problem by changing the above line of code to this:
g.drawLine((float)lBarX, 0, (float)lBarX, (float)lHeight-1, 1);



Based on the documentation of drawLine(), you should prefer fillRect():

    /** Draws a line between two points.
        The line is 1 pixel wide and drawn with the current colour or brush.
        TIP: If you're trying to draw horizontal or vertical lines, don't use this -
        it's better to use fillRect() instead unless you really need an angled line.

Maybe, but ideally drawLine() would work as documented - no doubt an iOS bug :slight_smile:

if you’re drawing vertical or horizontal lines, just use g.drawHorizontalLine() or g.drawVerticalLine().

That’s a really strange bug! Yes, definitely an iOS bug because when you call the other version of the method, it just doesn’t call CGContextStrokeLineSegments, and instead uses a path to draw it.

But looking at the code, it’s really odd that it could get it wrong like that… I’m at a loss for how we could change the native call to not trigger this crazy bug, so will just avoid using CGContextStrokeLineSegments and always draw the line as a path. I doubt whether that will be make much difference in performance, and TBH drawLine is probably best avoided anyway.

And since we have suggestions here on how best to draw it, it’s worth noting that the fastest (and actually least ambiguous over where exactly how the end of a 1-pixel line should be rendered) way to draw multiple vertical lines is with fillRectList.

drawLine is probably the worst way to do it, fillRect is better but if you’re doing more than one line, fillRectList avoids the significant overhead involved in making each call into the graphics stack and doing clipping etc for each rectangle. drawVerticalLine is simply a wrapper around a call to fillRect and only exists for backwards compatibility with the old days before scalable graphics made it pointless to have any operations that are optimised for 1-pixel 1:1 scale drawing.


I also stumbled upon this - really strange indeed. I was able to work around it by using drawHorizontalLine().

How lucky that googling

“cgcontextstrokelinesegments” bug

brought me here!