Drawing a one pixel line 2019

I saw some issues from 2016 talking about 125% desktop scaling on Windows 10 (which is very common) for trying to draw a single pixel line. I have been dealing with this issue with several UIs which are not very line dependent, but sometimes you really need a one pixel line for example for drawing a grid. What is the suggested way to draw a single pixel line using JUCE in 2019? Is there a way to draw a single line snapped to the hardware grid?

I don’t know if that helps with the scaling issues, but have you tried Graphics::drawHorizontalLine() and Graphics::drawVerticalLine()?
See: https://docs.juce.com/master/classGraphics.html#a6625d72cb899b3d213c3bb7a91409ff2

This one just fills a float rectangle internally, I have tried this, I have even tried to put all lines into paths and tried to paint them like that (this resulted in different unexpected behaviour but still wrong). Antialiasing is not what im looking for basically I want to paint straight to the physical pixel.

1 Like

I might be wrong, but I think the only way to achieve that is to write the graphics driver yourself.

It is 2019, there are so many different resolutions and pixel sizes, devices from 10cm to 10m. There will always be an abstraction layer from logical to physical pixels, unless it is a bespoke system.

4 Likes

I second that request. Not being able to draw a 1px line if the Windows user is using 125% is really weird. It always looks blurry and ugly and as plugin developer you don‘t care about 10m or 10cm screens.

Unfortunately, as an Operating System vendor, Microsoft doesn’t care about (some) plugin developers not caring about 10m or 10cm screens. :wink:

2 Likes

So how come that VisualStudio doesn‘t look blurry in 125%? :wink:

No idea, I avoid it as much as possible, and use Azure to build my Windows versions :joy:

You should try it, it‘s awesomely unblurry :wink:

Joke‘s aside, would it be possible to add a API call Graphics::draw1PxLine (along with his friend Graphics::draw1PxRect) that magically takes all scale factors into account and creates a float rectangle that is guaranteed to resolve to exactly one pixel on the screen?)

I sthis 1px logical or physical you’re after?

Well a “logical” pixel brought us this topic, so I guess a physical one :slight_smile:

Just a quick comparison between 100% and 125% (this example uses a AffineTransform within JUCE, but I can imagine, it’s the same for the global scale factor in Windows).

100% with a direct pixel to pixel correlation looks like this:

100percent

as opposed to 125%:

I hope the browser doesn’t rescale the images or this post will look like a crazy-person rant. If it doesn’t, you can clearly see the 100% view looks crisp and sharp and the 125% view looks like the familiy photos my father converted using a shareware image converter from 1995 :slight_smile:

Now I can live with the fact that the fonts are a bit more blurry (not sure why this is the case though, the vertical text was imported as .SVG so it should be 100% sharp). But the lines and especially the note rectangles look pretty cheap.

EDIT: Oh it does in fact rescale the images. You have to drag them to another browser tab to view them in their original resolution.

I can see the annoyance (I share it) but with display pixel densities going the way they are (and complexities such as sub-pixel rendering) a 1px physical line may not really be what you want (as it will be very thin on a 400ppi+ display).

It seems to me what this thread is asking is a way to draw a non-antialised line with a given minimum thickness which I’m not even sure is possible these days…

1 Like

Its more about having all the lines look the same independent of where they are positioned.

And this is precisely the thing that goes away on HiDPI displays as no matter where you draw the lines, there’s enough pixels that the edge aliasing is small in comparison (unless you really do draw a 1px physical line and you’re back to square one).

And this is precisely the thing that goes away on HiDPI displays.

Yes, but it doesn’t go away for the majority of your user base which has to cope with blurry user interfaces - or use a ridiculous small 100% version, which makes the whole “modern UIs can be scaled to match the screen size perfectly”-paradigm kind of pointless.

It seems to me what this thread is asking is a way to draw a non-antialised line with a given minimum thickness which I’m not even sure is possible these days…

Exactly. But since we can query which which CPU instructions are available on the current system (along with pretty much every other system property), I am pretty sure some smart person has thought about a way to get the actual logical-pixel to phyical pixel ratio for the current display. From then on, converting the Rectangle<float> that draws the blurred line into a version that doesn’t blur shouldn’t require a degree in rocket science.

I think we’re talking at cross purposes a bit. What I’m trying to get at is that sure, for the most common systems right now this is possible but it’s a constantly shifting ecosystem and I can imagine a time when all this physical hardware stuff is completely abstracted away from software APIs.

The other thing I’ve tried to clarify is what is actually being requested here as it’s certainly not as simple as “a 1px line”.

I’m also advocating that it’s really a free function helper method that should live outside of the standard JUCE drawing classes as it will likely need to know more than just the Graphics context such as the Display it’s currently on.

Does Displays::logicalToPhysical do what you need if you simply pass it a 1px rect?

Displays::logicalToPhysical. Nice one, exactly what I am looking for. Now I just need to traverse the component hierarchy and add all scale factors that are applied.

I still think that it should be part of the Graphics object, passing the current component you draw on as reference:

Graphics::draw1pxHorizontalLine(int y, int startX, int endX, Component* componentToDrawOn);

If you bury it in a helper tool class, people will not stumble upon it when browsing the Graphics API and keep on drawing blurry lines without knowing better.

Correct me if I’m wrong, but web-browsers don’t provide any mechanism for drawing physical-pixel-aligned graphics, right? How come the entire internet seems to be completely fine with the idea of providing carefully-designed graphics that run on every imaginable size and shape of screen… but plugin GUI people are constantly banging on about this as if it’s some kind of essential feature?

If you really, really want this, you can use LowLevelGraphicsContext::getPhysicalPixelScaleFactor() but be ready to deal with all kinds of stupid edge-cases as devices continue to move in the direction of simply not wanting people to get access to the pixels.

2 Likes

Another “plugin GUI people” here: We’re perfectly happy with the scaling and what it entails. It’s unavoidable. The user decides what resolution he wants his screen/apps to be in, not the developer. A 1px line is almost invisible on a 400 DPI screen.

If you really enforce all drawing primitives start and end on physical pixel edges, then your scaling will be all screwed up. Some events will be one pixel smaller than others, lines will be too thin etc.

Instead of fighting logical pixels, you should embrace them and design your artwork/layout to accommodate ANY resolution.

@jules is 100% right. The browsers scale it all and it looks really good.

3 Likes