4

One of the big problems with WPF is anti aliasing. In fact, that's why UseLayoutRending was introduced in WPF 4.0. However, it does not work for me in the following sample:

<StackPanel UseLayoutRounding="True" TextOptions.TextFormattingMode="Display" >
    <Line X1="0" Y1="0" X2="200" Y2="0" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
    <Line X1="0" Y1="1.5" X2="200" Y2="1.5" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
    <Line X1="0" Y1="3.5" X2="200" Y2="3.5" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
    <Line X1="0" Y1="7" X2="200" Y2="7" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
    <Line X1="0" Y1="9" X2="200" Y2="9" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
</StackPanel>

The last two lines are still blurry. (I am using Windows 7)

Any solution?

Or is it a bug in the beta of WPF 4.0?

tom greene
  • 5,361
  • 9
  • 39
  • 52

4 Answers4

2

Floele's answer showed the right direction, but the answer was not complete. Just set the y-values to half a pixel, e.g. Y1="7" -> Y1="7.5"

That's the reason the second and third lines are not blurred.

Kimke
  • 103
  • 8
2

Getting lines to look sharp in WPF can be quite hard! And some times ... it seems like it takes a bit of black magic too!

I think that floele and Kimke's answers are pointing in correct direction. That is, often times you will want to put single pixel lines on a 0.5 pixel boundary ... given the way that it draws the line (half on one side and half on another).

However, it isn't always that simple either. For example, it also depends on the surrounding xaml. For example, try this code out and resize when you do:

<Canvas HorizontalAlignment="Center" VerticalAlignment="Center">
    <Line X1="0" Y1="5" X2="200" Y2="5" StrokeThickness="1" Stroke="Black" UseLayoutRounding="True"/>
    <Line X1="0" Y1="15" X2="200" Y2="15" StrokeThickness="1" Stroke="Black" UseLayoutRounding="True"/>
</Canvas>

Then, try this code out (again, resize when you do):

<Canvas HorizontalAlignment="Center" VerticalAlignment="Center" UseLayoutRounding="True">
    <Line X1="0" Y1="5" X2="200" Y2="5" StrokeThickness="1" Stroke="Black"/>
    <Line X1="0" Y1="15" X2="200" Y2="15" StrokeThickness="1" Stroke="Black"/>
</Canvas>

The only difference between the two snippets is that the first uses UseLayoutRounding on the Lines while the second uses UseLayoutRounding on the Canvas container (which then also property inherit to the Lines).

However, that difference yields some interesting results. When UseLayoutRounding is used on the container the single pixel lines consistently stay spread out over 2 pixels and they don't move around. When UseLayoutRounding is used on the Lines directly, and you resize, the lines will sometimes be 1 pixel sharp ... and other times will be spead over 2 pixels.

And that brings me to the sample xaml in the original question. A few comments on it:

  1. First off, you should realize that both UseLayoutRounding and SnapsToDevicePixels property inherit. That is, if you use it on the layout container it will inherit to the items in the layout container.
  2. UseLayoutRounding and SnapsToDevicePixels shouldn't necessarily be used together. They can be ... but I would normally try using them separately ... either one or the other. More info here: When should I use SnapsToDevicePixels in WPF 4.0?
  3. TextOptions.TextFormattingMode options affect text, not lines.
  4. That StackPanel that you are using as the layout container could also affect how the lines are being laid out. Canvas allows you more precise positioning control of your lines. StackPanel will just layout one line after the other line ... and might yield some unexpected results.

More info than what the original poster was wanting. However, I personally know how tricky it is to get lines sharp in WPF. Hope this info helps someone!

Community
  • 1
  • 1
cplotts
  • 13,941
  • 9
  • 55
  • 66
1

The reason is apparently simpler. I only found an explanation in "Pro WPF in VB 2010" and not on MSDN though: http://books.google.de/books?id=F-gMZkAlUDUC&pg=PA334&lpg=PA334

In short, the StrokeThickness will be divided for both sides of a shape, so a StrokeThickness of 1 equals a thickness of 0.5 for each side, and since the line only has one side, it will be 0.5 units thick and thus appear blurry even when using SnapsToDevicePixels=True. So simply use "2" as StrokeThickness.

You can verify this by using a StrokeThickness of 4, the line will have a thickness of 2 then, which is more than an "accidential" single pixel deviation.

floele
  • 3,668
  • 4
  • 35
  • 51
  • Your last sentence is inaccurate. If you set a StrokeThickness of 4 ... it should either have a stroke thickness of 4 ... or it should have a stroke thickness of 3 with a half pixel on either side of the 3 solid pixels. – cplotts Dec 15 '14 at 16:59
  • @cplotts Why is it inaccurate? Did you get other results when testing? – floele Dec 16 '14 at 13:00
  • Most definitely @floele. I would be curious to see some sample code of what you describe. – cplotts Dec 16 '14 at 20:41
0

Have you tried to change the TextOptions.TextFormattingMode property to Display ? See this post from Lester Lobo for details

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758