Applying transforms to source xaml - wpf

I have a bit of a problem with XAML and Blend. We;ve converted the company logo from AI -> SVG -> XAML, cleaned it up a bit and its has produced a very peculiar source. In essence it is applying a "flip" transformation to a collection of paths:
<Canvas Width="640" Height="200" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas Width="640" Height="200" RenderTransform="1,0,0,-1,0,200" >
<!-- L -->
<Canvas RenderTransform="1,0,0,1,317.0645,64.3652">
<Path>
<Path.Data>
<PathGeometry FillRule="Nonzero" Figures="M0,0L0,75.065 18.743,76.83 18.743,17.066 43.553,17.066 38.564,0 0,0z" />
</Path.Data>
</Path>
</Canvas>
... etc
Note the RenderTransform="1,0,0,-1,0,200" node in the enclosing Canvas. It flips the canvas upside down and lowers it 200 down to adjust to root canvas position. Given taht Logo looks ok when rendered means that all graphic elements in the xaml are actually upside down :). Maybe its an AI thing, I don't know.
The problem is that I now use Blend to convert this canvas into a GraphicBrush. The blend omits the transform and the logo looks upiside down when brush is applied. Rather then again transforming at each brush recipient I was thinking that maybe we should just fix it at the root, e.g. convert all paths so that they render properly to begin with avoiding a need for root transform.
Question: is there a programmatic (or any other way) to do this? Meaning, can I render this canvas and then serialize a rendered (after all transforms applied) DOM into an XAML?
Or to make the question clearer: there are two transforms applied to each path (as seen above, one global flip and one local shift for each path), can I somehow apply those transforms to each path/its points so that paths render without them.

You can use the Export to XAML feature built in to Expression Design in the Microsoft Expression suite.
Or personally I normally use Mike Swanson's AI to XAML converter since I'm normally already working in Illustrator for more complex vector graphics.
Both would provide a better result than the converter you used. Not sure where that original conversion got so wacky with the RenderTransforms etc but as you've found, it helps to have a good conversion to start with then going through the trouble of fixing a bad one haha.
Cheers!

Related

WPF path description for a sine curve using bezier curves

I need to draw a sine curve (from x = 0 to 2pi) as part of a DrawingVisual and would like to use WPF's basic path capabilities to get a smooth curve. Probably I need some sort of bezier curve for that. Unfortunately I don't even know how they work. (Just that they can "pull" the line towards a control point somehow.)
Can somebody tell me what coordinates I should use to make it look right?
I could apply a ScaleTransform if I want to stretch it a little, so the normal form would be fine.
A thread in the MSDN forums just brought me in the middle of a formula mess in Wikipedia's scientific depths. I haven't studied maths so that's not much use to me.
Nevermind, I played a while with Kaxaml and found this pretty neat. It's probably a bit stretched already, but it makes the plot more recognisable.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Path Data="M0,100 L50,0 L50,200 L100,100" Stroke="Gray" StrokeThickness="0.5"/>
<Path Data="M0,100 C50,0 50,200 100,100" Stroke="Red" StrokeThickness="3"/>
</Grid>
</Page>
The first Path (grey) shows the control points used and how they are on the same horizontal offset; the second Path (red, bold) shows the final bezier curve.
This is how it looks like:

WPF: how to write text in a different direction?

I need to write text in the orientation specified for the image below. The fact is that I saw some examples around here by using a textblock and rotating the angle of the control using "RenderTransform", but this is not what I really need. I tried to do it using an image but it doesn't fit very well... so I really don't know how to solve it. If you look at the image beside you can see that the text is written from bottom to top and the line below the text is in the right of the screen.
This is the screen that I need to develop:
I tried by rotating the textblock, but the only way that it works for me was wrapping the text, but this is just the "closest" solution that I found. Also, as you can see, I need to set a border for the textblock.
Anyway, I hope you can help me because any example around fits with my problem.
In order to rotate your text at 90 degrees, I believe that you will need to use the LayoutTransform instead of the RenderTransform:
<TextBlock Text="FootRoller" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
The difference is when the transform will be applied. Using the LayoutTransform, the text will be rotated before the layout pass and this will be important in your case. I imagine that using the RenderTransform will rotate your TextBlock, but as it does that after the layout pass, it would not show it all... this is because it was measured for size before it was rotated.
You can find out full details from the Transforms Overview page on MSDN. From the linked page:
LayoutTransform – A transform that is applied before the layout pass. After the transform is applied, the layout system processes the transformed size and position of the element.
RenderTransform – A transform that modifies the appearance of the element but is applied after the layout pass is complete. By using the RenderTransform property instead of the LayoutTransform property, you can obtain performance benefits.
They're all right. RenderTransform should be all you need. Like;
<TextBlock Text="FootRoller" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.RenderTransform>
<CompositeTransform Rotation="-90"/>
</TextBlock.RenderTransform>
</TextBlock>
P.S. - You can literally just change RenderTransform to LayoutTransform which Sheridan has provided an explanation for in his answer.
If RenderTransform didn't work, take a look at LayoutTransform. You didn't tell us why RenderTransform didn't work but it's usually a safe bet that LayoutTransform will solve whatever problem it gave you.

Scaling an image with WP7 Silverlight with no smoothing algorithm applied

I have some images (32x32 .png) that I want to display in my Windows Phone 7 application. Right, now, I am able to scale them, etc... I was wondering if there was a way to scale them without any smoothing algorithms applied (so when I double the image size, it creates a blocky image look).
Right now in my XAML I have the following:
<Image Height="64" Width="64" Margin="12,0,9,0" Name="{Binding itemName}"
Stretch="Uniform" VerticalAlignment="Center" Source="{Binding imageName}" />
Where imageName is just a path to the .png images. Is there a simple way to do this in just XAML, or should I be loading the image into a different format to play with it in the code (while keeping the transparency of the png).
Thanks in advance,
-Jeff
Theres currently no way to do this in XAML. The only way to achieve a nearest neighbor scaling without any interpolation (smoothing) is the open source library WriteableBitmapEx.
http://writeablebitmapex.codeplex.com
First load the PNG into a WriteableBitmap, then use the Resize extension method the WriteableBitmapEx provides. Use the NearestNeighbor as value for the last parameter of the method. Then assign the return value of the Resize method to the Source property of your Image control.
You can wrap this functionality in an IValueConverter implementation so you can use it in XAML.

How to extend WPF hit testing zone for a Path object

Wpf hit testing is pretty good but the only method I found to extend the hit zone is to put a transparent padding area around your object. I can't find any method to add a transparent area arround a Path object. The path is very thin and I would like to enable hit testing if the user clicks near the path. I can't find any method to extend the path object with a transparent area like the image below :
alt text http://img175.imageshack.us/img175/6741/linepadding.png
I tried to used a partially transparent stroke brush but I ran into the problem described here : How can I draw a "soft" line in WPF (presumably using a LinearGradientBrush)?
I also tried to put an adorner over my line but because of WPF anti-aliasing algorithms, the position is way off when I zoom in my canvas and interfere with other objects hit-testing in a bad way.
Any suggestion to extend the hit testing zone would be highly appreciated.
Thanks,
Kumar
Path.Data is a geometry object. The Geometry class has several methods that can help you hit test with tolerance:
GetFlattenedPathGeometry(Double, ToleranceType)
GetOutlinedPathGeometry(Double, ToleranceType)
GetRenderBounds(Pen, Double, ToleranceType)
I think GetRenderBounds will work best for you.
Once you have the geometry (plus a little width) you can call
geometry.FillContains(Point, Double, ToleranceType)
or
geometry.StrokeContains(Pen, Point, Double, ToleranceType)
Out of all of that you should tune the desired hit from your hit test;
You can wrap the Path inside a transparent Border.
In WPF you can create another path with its geometry databound to the first (using Element Binding), but with transparent brush and increased thickness.
Something more or less like this:
<Path x:Name="backPath" Data="{Binding Data, ElementName=mainPath}" StrokeThickness="10" Stroke="Transparent"/>
<Path x:Name="mainPath" Data="{Binding DataFromViewModel}" StrokeThickness="1" Stroke="Red"/>
Note that the main path comes after in XAML, so that it is rendered on top.

Tiling rectangles seamlessly in WPF

I want to seamlessly tile a bunch of different-colored Rectangles in WPF. That is, I want to put a bunch of rectangles edge-to-edge, and not have gaps between them.
If everything is aligned to pixels, this works fine. But I also want to support arbitrary zoom, and ideally, I don't want to use SnapsToDevicePixels (because it would compromise quality when the image is zoomed way out). But that means my Rectangles sometimes render with gaps. For example:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black">
<Canvas SnapsToDevicePixels="False">
<Canvas.RenderTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
</Canvas.RenderTransform>
<Rectangle Canvas.Left="25" Width="100" Height="100" Fill="#CFC"/>
<Rectangle Canvas.Left="125" Width="100" Height="100" Fill="#CCF"/>
</Canvas>
</Page>
If the ScaleTransform's ScaleX is 1, then the Rectangles fit together seamlessly. When it's 0.5, there's a dark gray streak between them. I understand why -- the combined semi-transparent edge pixels don't combine to be 100% opaque. But I would like a way to fix it.
I could always just make the Rectangles overlap, but I won't always know in advance what patterns they'll be in (this is for a game that will eventually support a map editor). Besides, this would cause artifacts around the overlap area when things were zoomed way in (unless I did bevel-cut angles on the underlapping portion, which is an awful lot of work, and still causes problems at corners).
Is there some way I can combine these Rectangles into a single combined "shape" that does render without internal gaps? I've played around with GeometryDrawing, which does exactly that, but then I don't see a way to paint each RectangleGeometry with a different-colored brush.
Are there any other ways to get shapes to tile seamlessly under an arbitrary transform, without resorting to SnapsToDevicePixels?
You might consider using guidelines (see GuidelineSet on MSDN) and overriding the Rectangles' OnRender methods so that their boundaries line up with the pixel boundaries of the device. WPF uses guidelines to determine whether and where to snap drawings.
Internally, it's exactly what SnapsToDevicePixels is using to ensure that objects line up with the device's pixels, but by placing guidelines manually you'll be able to control when the snapping behaviour is applied and when it is not (so when your image is zoomed all of the way out, you can avoid drawing guidelines, or only draw guidelines where your shapes lie next to other shapes, and rely on WPF's anti-aliasing to take care of the rest). You might be able to do it with an attached property so that you can apply it to any element, though if it's only one type of element (e.g. Rectangle) that you need this behaviour on, it's probably not worth the extra effort.
It seems like Microsoft is aware of this problem, too - WPF 4.0 is expected to feature Layout Rounding, which, like the version in Silverlight, rounds off non-integer values at the Render pass when layout rounding has been enabled.
I guess the gaps are not actual gaps but the stroke that is painted. When you scale it down than you just make the stroke smaller to a point where it is not visible anymore. I tried to paint the stroke in the color of the rectangle wich works just fine on any scale.
&ltPage xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black"&gt
&ltCanvas SnapsToDevicePixels="False"&gt
&ltCanvas.RenderTransform&gt
&ltScaleTransform ScaleX="0.5" ScaleY="0.5"/&gt
&lt/Canvas.RenderTransform&gt
&ltRectangle Canvas.Left="25" Width="100" Height="100" Fill="#CFC" Stroke="#CFC"/&gt
&ltRectangle Canvas.Left="125" Width="100" Height="100" Fill="#CCF" Stroke="#CCF"/&gt
&lt/Canvas&gt
&lt/Page&gt

Resources