Felice Pollano
Felice Pollano

Reputation: 33252

WPF DrawingContext seems ignore SnapToDevicePixels

I'm drawing a chart by direct calls to DrawLine on the DrawingContext. Since I want to avoid any anti aliasing feature, I tryed to put the SnapToDevicePixels=true on the parent UIElement, but I still have anti-alias:

enter image description here

The project was an old OS project not written for WPF4, but I retarget it to the Framework4, can this be an issue too ?

Upvotes: 18

Views: 4816

Answers (3)

walterlv
walterlv

Reputation: 2376

GuidelineSet is designed to resolve your problems.

@Marat Khasanov recommended you to use GuidelineSet and you replied that it messed up your code. I'm also suffering from this problem, so I write the code below to solve this problem with non-ugly code.

Notice: This method works even in a Viewbox.

public static class SnapDrawingExtensions
{
    public static void DrawSnappedLinesBetweenPoints(this DrawingContext dc,
        Pen pen, double lineThickness, params Point[] points)
    {
        var guidelineSet = new GuidelineSet();
        foreach (var point in points)
        {
            guidelineSet.GuidelinesX.Add(point.X);
            guidelineSet.GuidelinesY.Add(point.Y);
        }
        var half = lineThickness / 2;
        points = points.Select(p => new Point(p.X + half, p.Y + half)).ToArray();
        dc.PushGuidelineSet(guidelineSet);
        for (var i = 0; i < points.Length - 1; i = i + 2)
        {
            dc.DrawLine(pen, points[i], points[i + 1]);
        }
        dc.Pop();
    }
}

Call the method in OnRender and pass line points to it.

protected override void OnRender(DrawingContext dc)
{
    // Draw four horizontal lines and one vertical line.
    // Notice that even the point X or Y is not an integer, the line is still snapped to device.
    dc.DrawSnappedLinesBetweenPoints(_pen, LineThickness,
        new Point(0, 0), new Point(320, 0),
        new Point(0, 40), new Point(320, 40),
        new Point(0, 80.5), new Point(320, 80.5),
        new Point(0, 119.7777), new Point(320, 119.7777),
        new Point(0, 0), new Point(0, 120));
}

Here is the render result in a viewbox: snapped result

Upvotes: 3

Markus H&#252;tter
Markus H&#252;tter

Reputation: 7906

I found this link where they basically say you should set

ParentUIElement.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);

It worked for me, so it might be worth a try!

Upvotes: 17

Marat Khasanov
Marat Khasanov

Reputation: 3848

SnapsToDevicePixels works only for element bounding box. You need to use Guidelines with DrawingContext. Also you can specify VisualXSnappingGuidelines and VisualYSnappingGuidelines if it fits to your requirements.

Upvotes: 4

Related Questions