The function that I use for drawing frequency lines (the horizontal version for dB is similar) is:
const auto drawFreqLine = [&] (float freq) -> void
{
const auto x = floor (freqToX (freq)) + 0.5f;
drawPathLine (x, 0, x, height);
};
so, I clearly forced the lines to be āin betweenā pixels.
If I had used the float results from my freqToX () function, I would have had āsomeā lines with aliasing, depending on them being closer to .0f then to .5f.
This works for me and helps me forget the differences between, drawLine, drawPath, fillRect, etc. (ok, there are some comments in the code, for the next time I run into such issues).
I think there is something wrong in the juce code because Iām pretty sure I had not the issue before, and I have no way to get a clean line from pretty simple example. (Iām using Juce 6.1.6 wich is the latest version)
If someone in the Juce team could help here it would be greatā¦
Well, one thing is clear to me: you do not read well (enough)ā¦
You just add 0.5f by scanning my reply, but you do not use std::floor. Where is it? Did you understand my explanation?
By throwing in the += 0.5f you make my advice look like a hack, which it certainly is not.
Then you say āWe see a 2px lineā.
Well, I see an āaliased 1px Juce lineā, starting at a .0f pixel location.
Make sure it starts between pixels, thus with a value ending exactly at .5f.
A tip: get a ālinterā, or some tool that helps you to show mistakes in your source code before you even compile it, I suggest ReSharper (for Visual Studio), and/or AppCode, for Mac - both from JetBrains.
You are mixing floats and ints. Donāt.
getWidth () returns an int and you are mixing that with floats.
Even in one single line you use:
getWidth() - 1.0 // that's a double! Not even a float
and
getWidth() - 1
No compilation errors, but this kind of coding will surely get you into troubles.
In this particular case the floor function has no use, because we start with an integer getWidth () value. So the offset is nicely moved to a 0.5f value by the addition.
In situations with calculated floating point positions, like my Eq grid example, it is needed.
And I would not use a fillPath approach in a simple situation like this, but a fillRect () - this is just to continue with my example from above.
Sorry if I missed your point. I understood that we want to always be inbetween pixels in order to draw a clean one pixel line. So always using values like 1.5, 2.5, etc. You add 0.5 to be inbetween and add the floor to secure the case where your input value stacks up with an other decimal value as 0.5. Am I correct ?
Your advice was obviously good as it is more generic. I get rid of floor as I was focused on this specific use case where I know for sure the drawPathLine will not have a float input with decimal part.
Even using your last code example I have the artifactsā¦
On your first question: I use the floor () plus 0.5f for any calculated floating point value.
It is not about āstackingā other 0.5f values.
If I calculate the position for a frequency or a dB value I donāt think in values like 0.0f or 0.5f - they can be anything in between. And with Juceās path, anything not ending with 0.5f will show aliasing. Simple.
And on your latest screen shots: really weird. I also zoomed in on the first picture, in order to check it is not a zooming issue (avoid the Windows zoom tool! Or be aware that it introduces aliasing, seriously). But the issue is indeed in the small image as well.
I checked my example also on a Mac with Retina (because I develop on Windows). Also OK. Latest Juce develop. Unfortunately I cannot test with another DPI environment.
Have you tried drawing a 0.5f wide line? I would start testing a lot of weird ideas in a situation like thisā¦
It depends on what you mean with āhandle this properlyā: if you wish your coordinates to always match the pixels on the screen ignoring Windowsā scale setting, then you should disable DPI awareness for your window, but that comes at the cost that if a user wanted its scale set to 200% because he has a highDPI monitor, your window will still appear as if he had set 100% for your window, i.e. very small compared to his expectations.
If you want your window to follow the (non-integer) global scale set in Windows, then some blurring/antialiasing/artifacts are expected because logical coordinates no longer precisely match with the hardware pixels āunderneathā