3

I'm trying to draw a very thin line (less than one pixel thick) in android. I'm using

Paint blackThin = new Paint();
blackThin.setStrokeWidth(0.1f);
blackThin.setColor(Color.BLACK);

to initialize the paint object.

This works fine in Android 2.2, but when I try it in 4.2 (also 4.1, I think - I tested that one briefly - I haven't tested any other versions other that 2.2, 4.1.2 and 4.2) the lines won't show up when I draw them. To make them show up in 4.2, it seems like I have to set the anti-aliasing flag to be true. (I tried that, and the lines showed up.) But I really don't want that, because that blurs the lines and such.

Is this a bug in Android? Is there something I can do to make it work other than turning on anti-aliasing?

EDIT: I also tested this with a pixel size of 0.9, and the problem is the same.

Thanks for the help!

Shdus
  • 83
  • 1
  • 6
  • 3
    What do you expect a 0.1 pixel thick line to look like without anti-aliasing? – Matti Virkkunen Jan 01 '13 at 23:31
  • In version 2.2, it works fine. It's just a very thin line. And as an aside, 0.9 has the same problem as 0.1. – Shdus Jan 01 '13 at 23:35
  • 3
    More likely: in 2.2 it's working accidentally. The smallest thing that can be drawn is a single pixel, why are you expecting things to be drawn that are smaller than that? – robertc Jan 01 '13 at 23:51

2 Answers2

3

If you want a very thin line, use setStrokeWidth(0), as the documentation says Pass 0 to stroke in hairline mode.

Sub-pixel drawing obviously requires Anitaliasing or other workarounds. It is pretty possible that e.g. with software rendering, lines below one pixel are always drawn as hairlines, but with hardware rendering (which may be automatically used in Android 4.2 but not in 2.2), the behavior changes and many of the convenient features disappear. (This is often the reason for drawing differences and weird glitches, btw.)

Jan Schejbal
  • 4,000
  • 19
  • 40
  • I saw that documentation and tried it, but using setStrokeWidth(0) gave me the same results as if I had used setStrokeWidth(1). Did I have to set a certain flag to get that to work? Also, I'm using the emulator. Could that be effecting it? – Shdus Jan 01 '13 at 23:46
  • I'm not sure, you should always also test on a real device. You could try to disable hardware rendering (see [doc](http://developer.android.com/guide/topics/graphics/hardware-accel.html)) for testing. Although the hairline mode drawing is not mentioned to be an issue, the doc might be incomplete. Also, why are you trying to make a sub-pixel line without antialiasing instead of setting it to 1 px and possibly adjusting the color? – Jan Schejbal Jan 01 '13 at 23:50
  • Unfortunately, I don't have direct access to a newer device. But you are 100% right about that! I tried playing around with different combinations of hardware acceleration settings without success. Thanks for the idea, though. What are you suggesting? Making a 1 px line but using a lighter color so it looks smaller? – Shdus Jan 02 '13 at 00:10
  • Yes, 1px line with lighter color is exactly what you need if you really want to make it look smaller without enabling antialiasing (you are basically doing antialiasing manually then). However, consider that a 1px line on xhdpi devices with 300+ dpi is already very very thin. – Jan Schejbal Jan 02 '13 at 13:27
3

You can't draw lines less than a pixel in width without anti-aliasing.

The whole point of anti-aliasing is to calculate what a pixel's colour would be, if a element doesn't completely fill the pixel (Like a line that's only a tenth of a pixel's width).

You could somewhat simulate it by drawing a lighter line, but that still wouldn't come close to a actually anti-aliased line.

Take a look at this image, for example:

enter image description here

It's really not possible to replicate the anti-aliased result by changing the line's colour.

I realise the lines in the example are > 1 pixel in width, but the same principle applies. The "darkness" of a pixel is calculated as a result of how much of the pixel is filled with the line. For that reason, a solid grey line won't work.

Cerbrus
  • 70,800
  • 18
  • 132
  • 147