I am wondering if someone has managed to override the default behaviour of the WPF shape rendering when applying a scaletransform to the shape. The default behaviour transforms the entire shape drawing, including strokes, but I would like to only scale the geometry. The difficulty is that my shapes reside in a visual hierarchy with render transforms applied on different levels (sort of like a 2D scene graph but a WPF visual tree), this I cannot change(!). I have read in different places that it might be possible to create a custom shape to cancel out the transform for the render transform and put it on the geometry instead. At the moment I have something like:
public sealed class MyPath : Shape
{
// This class has a Data property of type Geometry just like the normal Path class
protected override Geometry DefiningGeometry
{
get
{
Geometry data = Data;
if (data == null)
{
data = Geometry.Empty;
}
return data;
}
}
protected override void OnRender(DrawingContext drawingContext)
{
Transform tr = RenderedGeometry.Transform;
Geometry geomToDraw = RenderedGeometry.Clone();
geomToDraw.Transform = new MatrixTransform(tr.Value * tr.Value);
Matrix trInv = tr.Value; trInv.Invert();
drawingContext.PushTransform(new MatrixTransform(trInv));
drawingContext.DrawGeometry(Brushes.Transparent, new Pen() { Brush = Brushes.Black, Thickness = 1 }, geomToDraw);
}
}
As is clearly evident, I am quite new to this and the above code is probably completely messed up. I was trying to transfer the matrix to the geometry without changing the final resulting geometry transform, hence the tr.Value*tr.Value and trInv. But it does not work as I want it to. I know this transfer transform technique works in theory because I tried it out with constant transforms (testing to set Geometry.Transform to scale x with 4 and pushing a transform to scale x with 0.25 worked fine but the resulting shape drawing did not seem to apply stretch=fill, which I rely upon). So there must be something that I am missing with the render transforms.
The test scenario that is not working is this:
- I apply a render scale transform with scaleX=4 and scaleY=1 in xaml.
- The built-in Path class scales the entire drawing so that strokes 4 times wider in the x direction than in the y direction.
- I want MyPath to scale the geometry only, not the strokes. <- THIS IS NOT WORKING!
- What happens is: The geometry gets scaled correctly, the strokes get scaled by 4 in the x direction and by slightly less than 4 in the y direction. What is wrong? I have a feeling that I should not be working solely with RenderedGeometry.Transform but what should I use instead? I need to incorporate the render transform and the stretch=fill on the shape. My render transforms hierarchy may contain a mix of scales, rotations and translations so the solution must be general enough to handle any transform, not just axis-aligned scaling.
Note: I know it is bad to create the geometry in OnRender but I want to get it working before spending time cleaning it up.
By the way, I read this post:
Invariant stroke thickness of Path regardless of the scale
The problem as stated before is that I do have to take render transforms into consideration and I am not sure of how to adapt that solution to work with them.