2

I'm trying to do simple drawing in a subclass of a decorator, similar to what they're doing here...

How can I draw a border with squared corners in wpf?

...except with a single-pixel border thickness instead of the two they're using there. However, no matter what I do, WPF decides it needs to do its 'smoothing' (e.g. instead of rendering a single-pixel line, it renders a two-pixel line with each 'half' about 50% of the opacity.) In other words, it's trying to anti-alias the drawing. I do not want anti-aliased drawing. I want to say if I draw a line from 0,0 to 10,0 that I get a single-pixel-wide line that's exactly 10 pixels long without smoothing.

Now I know WPF does that, but I thought that's specifically why they introduced SnapsToDevicePixels and UseLayoutRounding, both of which I've set to 'True' in the XAML. I'm also making sure that the numbers I'm using are actual integers and not fractional numbers, but still I'm not getting the nice, crisp, one-pixel-wide lines I'm hoping for.

Help!!!

Mark

Community
  • 1
  • 1
Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286

2 Answers2

2

Aaaaah.... got it! WPF considers a line from 0,0 to 10,0 to literally be on that logical line, not the row of pixels as it is in GDI. To better explain, think of the coordinates in WPF being representative of the lines drawn on a piece of graph paper whereas the pixels are the squares those lines make up (assuming 96 DPI that is. You'd need to adjust accordingly if they are different.)

So... to get the drawing to refer to the pixel locations, we need to shift the drawing from the lines themselves to be the center of the pixels (squares on graph paper) so we shift all drawing by 0.5, 0.5 (again, assuming a DPI of 96)

So if it is a 96 DPI setting, simply adding this in the OnRender method worked like a charm...

drawingContext.PushTransform(new TranslateTransform(.5, .5));

Hope this helps others!

M

Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
  • 1
    Thank you very much Marque! Your explanation make me understand why my drawing need to be 0.5 padding to work unblurried. Thanks again! –  Oct 11 '11 at 15:05
  • No problem! That's what we're here for! :) Actually, for the same reason, if that was helpful, mind voting up my answer? Thanks! :) – Mark A. Donohoe Oct 11 '11 at 17:35
1

Have a look at this article: Draw lines exactly on physical device pixels

UPD

Some valuable quotes from the link:

The reason why the lines appear blurry, is that our points are center points of the lines not edges. With a pen width of 1 the edges are drawn excactly between two pixels.

A first approach is to round each point to an integer value (snap to a logical pixel) an give it an offset of half the pen width. This ensures, that the edges of the line align with logical pixels.

Fortunately the developers of the milcore (MIL stands for media integration layer, that's WPFs rendering engine) give us a way to guide the rendering engine to align a logical coordinate excatly on a physical device pixels. To achieve this, we need to create a GuidelineSet

protected override void OnRender(DrawingContext drawingContext)
{
    Pen pen = new Pen(Brushes.Black, 1);
    Rect rect = new Rect(20,20, 50, 60);

    double halfPenWidth = pen.Thickness / 2;

    // Create a guidelines set
    GuidelineSet guidelines = new GuidelineSet();
    guidelines.GuidelinesX.Add(rect.Left + halfPenWidth);
    guidelines.GuidelinesX.Add(rect.Right + halfPenWidth);
    guidelines.GuidelinesY.Add(rect.Top + halfPenWidth);
    guidelines.GuidelinesY.Add(rect.Bottom + halfPenWidth);

    drawingContext.PushGuidelineSet(guidelines);
    drawingContext.DrawRectangle(null, pen, rect);
    drawingContext.Pop();
}
Marat Khasanov
  • 3,808
  • 19
  • 22
  • I had basically just figured that out, but I'm marking yours as accepted since you included the article. (Plus, who likes marking their own questions as answered by them?) – Mark A. Donohoe Apr 11 '11 at 20:40
  • There have been various threads on the meta sites such as [this one](http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers) that come to the conclusion that link-only answers are not very helpful. Links can go dead, so please at least provide explain the gist of the linked site here. – O. R. Mapper May 17 '14 at 08:39