Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
XAML WPF Canvas conversion to Mako DOM, leveraging the Abbreviated Geometry Syntax support introduced in Mako 6.3.0
/* --------------------------------------------------------------------------------
* <copyright file="XamlToMakoDom.cs" company="Global Graphics Software Ltd">
* Copyright (c) 2021 Global Graphics Software Ltd. All rights reserved.
* </copyright>
* <summary>
* This example is provided on an "as is" basis and without warranty of any kind.
* Global Graphics Software Ltd. does not warrant or make any representations
* regarding the use or results of use of this example.
* </summary>
* ---------------------------------------------------------------------------------
*/
using System;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Xml;
using JawsMako;
namespace XamlToMakoDom
{
public class XamlToMakoDom
{
public static int Main()
{
try
{
// Startup Mako
var mako = IJawsMako.create();
IJawsMako.enableAllFeatures(mako);
// Load the XAML
XmlDocument xaml = new XmlDocument();
xaml.Load("FunnyRobot.xaml");
XmlNode xmlNode = xaml.DocumentElement;
// Convert the XAML to Mako DOM objects, adding to an IDOMGroup
IDOMGroup group = IDOMGroup.createInstance(mako);
AddToGroup(ref mako, ref group, xmlNode);
// Create a new assembly, document, page
using var assembly = IDocumentAssembly.create(mako);
using var document = IDocument.create(mako);
using var page = IPage.create(mako);
document.appendPage(page);
assembly.appendDocument(document);
// Add the graphic to a new fixed page (Mako defaults to A4) then save as PDF
using var fixedPage = IDOMFixedPage.create(mako);
page.setContent(fixedPage);
fixedPage.appendChild(group);
IPDFOutput.create(mako).writeAssembly(assembly, "geometry.pdf");
}
catch (MakoException e)
{
string errorString = e.m_msg;
Console.WriteLine($"Mako exception thrown: {e.m_errorCode} {e.m_msg}");
return (int) e.m_errorCode;
}
return 0;
}
// Create Mako DOM from XAML markup
static void AddToGroup(ref IJawsMako mako, ref IDOMGroup idomGroup, XmlNode xmlNode)
{
double width = 0, height = 0, canvasLeft = 0, canvasTop = 0, strokeThickness = 0, strokeMiterLimit = 0;
string stretch;
IDOMPathNode.eStrokeLineJoin eStrokeLineJoin = IDOMPathNode.eStrokeLineJoin.eMiterJoin;
IDOMPathGeometry clip = IDOMPathGeometry.Null();
IDOMPathGeometry geometry = IDOMPathGeometry.Null();
IDOMBrush strokeColor = IDOMBrush.Null(), fillColor = IDOMBrush.Null(), background = IDOMBrush.Null();
string data = string.Empty;
var attributes = xmlNode.Attributes;
if (attributes != null)
{
double.TryParse(attributes["Width"]?.Value, out width);
double.TryParse(attributes["Height"]?.Value, out height);
double.TryParse(attributes["Canvas.Left"]?.Value, out canvasLeft);
double.TryParse(attributes["Canvas.Top"]?.Value, out canvasTop);
var clipData = attributes["Clip"]?.Value;
if (clip != null)
clip = IDOMPathGeometry.create(mako, clipData);
}
// Grouping (non-marking) nodes
if (xmlNode.LocalName == "Canvas" || xmlNode.LocalName == "Viewbox")
{
var idomCanvas = IDOMGroup.create(mako, new FMatrix(1.0, 0.0, 0.0, 1.0, canvasLeft, canvasTop),
clip);
idomGroup.appendChild(idomCanvas);
AddToGroup(ref mako, ref idomCanvas, xmlNode.FirstChild);
}
else if (xmlNode.LocalName == "TextBlock")
{
string text = string.Empty, fontFamily = "Arial";
double fontSize = 0;
var textMatrix = new FMatrix();
for (int i = 0; i < xmlNode.ChildNodes.Count; i++)
{
var childNode = xmlNode.ChildNodes[i];
// Text run
if (childNode?.LocalName == "Run")
{
var textAttributes = childNode.Attributes;
fontFamily = textAttributes?["FontFamily"]?.Value;
double.TryParse(textAttributes?["FontSize"]?.Value, out fontSize);
text = textAttributes?["Text"]?.Value;
fillColor = MakoSolidColorBrush(mako, textAttributes?["Foreground"]?.Value);
background = MakoSolidColorBrush(mako, textAttributes?["Background"]?.Value);
}
// Text scale and position
if (childNode?.LocalName == "TextBlock.RenderTransform")
{
var transformGroup = childNode.FirstChild;
for (int j = 0; j < transformGroup?.ChildNodes.Count; j++)
{
var transformGroupItem = transformGroup.ChildNodes[j];
if (transformGroupItem?.LocalName == "MatrixTransform")
{
var matrixValues = transformGroupItem.Attributes?[0].Value;
var mx = matrixValues?.Split(',').Select(Convert.ToDouble).ToArray();
textMatrix = new FMatrix(mx[0], mx[1], mx[2], mx[3], mx[4], mx[5]);
}
}
}
}
// Find the font
var font = mako.findFont(fontFamily, out var fontIndex);
// Create the glyphs
var glyphs = IDOMGlyphs.create(mako, text, fontSize, new FPoint(), fillColor, font, fontIndex, IDOMGlyphs.eStyleSimulations.eSSNone, textMatrix);
// The vertical position is adjusted downwards by the font height + 10%, as XAML and Mako use different Y-axis origin
textMatrix.setDY(textMatrix.dy() + (glyphs.getBounds().dY * 1.1));
glyphs.setRenderTransform(textMatrix);
// Add background?
if (background != null)
{
// Adjust height. XAML bounding box is taller that Mako's
var makoBounds = glyphs.getBounds();
var delta = (makoBounds.dY * 1.355) - makoBounds.dY;
var xamlBounds = new FRect(makoBounds.x, makoBounds.y - (delta * 0.78),
makoBounds.dX, makoBounds.dY + delta);
idomGroup.appendChild(IDOMPathNode.createFilled(mako,
IDOMPathGeometry.create(mako, xamlBounds), background));
}
// Add to the group
idomGroup.appendChild(glyphs);
}
else
{
// Marking nodes
if (attributes != null)
{
stretch = attributes["Stretch"]?.Value;
double.TryParse(attributes["StrokeThickness"]?.Value, out strokeThickness);
double.TryParse(attributes["StrokeMiterLimit"]?.Value, out strokeMiterLimit);
string strokeLineJoin = attributes["StrokeLineJoin"]?.Value;
if (strokeLineJoin == "Round")
eStrokeLineJoin = IDOMPathNode.eStrokeLineJoin.eRoundJoin;
if (strokeLineJoin == "Bevel")
eStrokeLineJoin = IDOMPathNode.eStrokeLineJoin.eBevelJoin;
data = attributes["Data"]?.Value;
// Create geometry
switch (xmlNode.LocalName)
{
case "Path":
geometry = IDOMPathGeometry.create(mako, data);
break;
case "Rectangle":
geometry = IDOMPathGeometry.create(mako,
new FRect(canvasLeft, canvasTop, width, height));
break;
case "Ellipse":
geometry = IDOMPathGeometry.createEllipse(mako,
new FRect(canvasLeft, canvasTop, width, height));
break;
}
// Apply fill
var fill = attributes["Fill"];
if (fill == null)
{
if (xmlNode.FirstChild?.LocalName == "Path.Fill")
fillColor = MakoGradientBrush(mako, xmlNode.FirstChild?.InnerXml, geometry.getBounds(false));
}
else
fillColor = MakoSolidColorBrush(mako, fill.Value);
// Apply stroke
var stroke = attributes["Stroke"];
if (stroke == null)
{
if (xmlNode.FirstChild?.LocalName == "Path.Stroke")
strokeColor = MakoGradientBrush(mako, xmlNode.FirstChild?.InnerXml, geometry.getBounds(false));
}
else
strokeColor = MakoSolidColorBrush(mako, stroke.Value);
}
// Create filled object
if (fillColor != null)
{
IDOMPathNode fillPath = IDOMPathNode.createFilled(mako, geometry, fillColor);
idomGroup.appendChild(fillPath);
}
// Create stroked object
if (strokeColor != null && strokeThickness > 0)
{
var strokePath = IDOMPathNode.createStroked(mako, geometry, strokeColor);
strokePath.setStrokeThickness(strokeThickness);
strokePath.setStrokeLineJoin(eStrokeLineJoin);
if (strokeMiterLimit > 0)
strokePath.setStrokeMiterLimit(strokeMiterLimit);
idomGroup.appendChild(strokePath);
}
}
var nextSibling = xmlNode.NextSibling;
if (nextSibling != null)
AddToGroup(ref mako, ref idomGroup, nextSibling);
}
// Mako solid color brush from XAML color definition
static IDOMBrush MakoSolidColorBrush(IJawsMako mako, string xamlColor)
{
return xamlColor != null ? IDOMBrush.fromRCObject(IDOMSolidColorBrush.create(mako, MakoColor(mako, xamlColor)).toRCObject()) : IDOMBrush.Null();
}
// Mako RGB color from XAML color definition
static IDOMColor MakoColor(IJawsMako mako, string xamlColor)
{
var color = xamlColor.StartsWith('#') ? ColorTranslator.FromHtml(xamlColor) : Color.FromName(xamlColor);
return IDOMColor.create(mako, IDOMColorSpacesRGB.create(mako),
color.A / 255.0, color.R / 255.0, color.G / 255.0, color.B / 255.0);
}
// Mako gradient brush
static IDOMBrush MakoGradientBrush(IJawsMako mako, string xml, FRect boundingBox)
{
var linearGradientBrush = IDOMLinearGradientBrush.createInstance(mako);
linearGradientBrush.setStartPoint(new FPoint(boundingBox.x, boundingBox.y));
linearGradientBrush.setEndPoint(new FPoint(boundingBox.x + boundingBox.dX, boundingBox.y + boundingBox.dY));
XmlDocument fillAttr = new XmlDocument();
fillAttr.LoadXml(xml);
var firstChild = fillAttr.FirstChild;
if (firstChild?.LocalName == "LinearGradientBrush")
{
if (firstChild.Attributes != null)
{
var sp = firstChild.Attributes["StartPoint"]?.Value;
if (sp != null)
{
var pv = sp.Split(',').Select(Convert.ToDouble).ToArray();
linearGradientBrush.setStartPoint(new FPoint(boundingBox.x + pv[0] * boundingBox.x, boundingBox.y + pv[1] * boundingBox.y));
}
var ep = firstChild.Attributes["EndPoint"]?.Value;
if (ep != null)
{
var pv = ep.Split(',').Select(Convert.ToDouble).ToArray();
linearGradientBrush.setEndPoint(new FPoint(boundingBox.x + pv[0] * boundingBox.dX, boundingBox.y + pv[1] * boundingBox.dY));
}
}
for (var i = 0; i < firstChild.ChildNodes.Count; i++)
{
var node = firstChild.ChildNodes[i];
if (node is not {LocalName: "GradientStop"}) continue;
var stopColor = MakoColor(mako, node.Attributes["Color"].Value);
double.TryParse(node.Attributes["Offset"]?.Value, out var offset);
linearGradientBrush.addGradientStop(IDOMGradientStop.create(mako, stopColor, offset));
}
}
return IDOMBrush.fromRCObject(linearGradientBrush.toRCObject());
}
} // End class
}
<?xml version="1.0" encoding="utf-8"?>
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="FunnyRobot" Width="266.667" Height="600" Clip="F1 M 0,0L 266.667,0L 266.667,600L 0,600L 0,0">
<Canvas x:Name="Layer_2" Width="266.667" Height="600" Canvas.Left="0" Canvas.Top="0">
<Path Width="187.896" Height="187.897" Canvas.Left="38.775" Canvas.Top="98.9014" Stretch="Fill" Data="F1 M 208.914,286.799L 56.5324,286.799C 46.7257,286.799 38.775,278.848 38.775,269.041L 38.775,116.66C 38.775,106.852 46.7257,98.9014 56.5324,98.9014L 208.914,98.9014C 218.722,98.9014 226.671,106.852 226.671,116.66L 226.671,269.041C 226.671,278.848 218.722,286.799 208.914,286.799 Z ">
<Path.Fill>
<LinearGradientBrush EndPoint="1,0">
<GradientStop Color="#FFFF9B28" Offset="0"/>
<GradientStop Color="#FFFFD03C" Offset="0.4"/>
<GradientStop Color="#FFF7931E" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path Width="212.699" Height="41.9553" Canvas.Left="26.4732" Canvas.Top="286.799" Stretch="Fill" Fill="#FF29ABE2" Data="F1 M 26.4732,313.981C 26.4732,313.981 144.726,348.505 239.172,311.997L 214.568,286.799L 54.6478,286.799L 26.4732,313.981 Z "/>
<Viewbox Width="125.936" Height="31.8886" Canvas.Left="70.6482" Canvas.Top="230.279">
<Canvas Width="125.936" Height="31.8886">
<Path Width="16.6107" Height="16.6111" Canvas.Left="-2.80142e-006" Canvas.Top="2.48031" Stretch="Fill" StrokeThickness="1.33333" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 15.944,10.7856C 15.944,15.0043 12.524,18.4247 8.30534,18.4247C 4.08666,18.4247 0.666664,15.0043 0.666664,10.7856C 0.666664,6.56699 4.08666,3.14697 8.30534,3.14697C 12.524,3.14697 15.944,6.56699 15.944,10.7856 Z "/>
<Path Width="16.6107" Height="16.6106" Canvas.Left="26.5873" Canvas.Top="10.1191" Stretch="Fill" StrokeThickness="1.33333" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 42.5313,18.4244C 42.5313,22.6431 39.1113,26.0631 34.8927,26.0631C 30.674,26.0631 27.254,22.6431 27.254,18.4244C 27.254,14.2058 30.674,10.7858 34.8927,10.7858C 39.1113,10.7858 42.5313,14.2058 42.5313,18.4244 Z "/>
<Path Width="16.6107" Height="16.6106" Canvas.Left="53.7699" Canvas.Top="15.2779" Stretch="Fill" StrokeThickness="1.33333" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 69.7139,23.5833C 69.7139,27.8019 66.2939,31.2219 62.0752,31.2219C 57.8565,31.2219 54.4365,27.8019 54.4365,23.5833C 54.4365,19.3646 57.8565,15.9446 62.0752,15.9446C 66.2939,15.9446 69.7139,19.3646 69.7139,23.5833 Z "/>
<Path Width="16.6107" Height="16.6106" Canvas.Left="83.9285" Canvas.Top="10.1191" Stretch="Fill" StrokeThickness="1.33333" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 99.8725,18.4244C 99.8725,22.6431 96.4525,26.0631 92.2339,26.0631C 88.0152,26.0631 84.5952,22.6431 84.5952,18.4244C 84.5952,14.2058 88.0152,10.7858 92.2339,10.7858C 96.4525,10.7858 99.8725,14.2058 99.8725,18.4244 Z "/>
<Path Width="16.6106" Height="16.6107" Canvas.Left="109.325" Canvas.Top="-1.04308e-005" Stretch="Fill" StrokeThickness="1.33333" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 125.269,8.30533C 125.269,12.524 121.849,15.944 117.631,15.944C 113.412,15.944 109.992,12.524 109.992,8.30533C 109.992,4.08667 113.412,0.666656 117.631,0.666656C 121.849,0.666656 125.269,4.08667 125.269,8.30533 Z "/>
</Canvas>
</Viewbox>
<Path Width="49.464" Height="32.031" Canvas.Left="7.56516" Canvas.Top="384.331" Stretch="Fill" Fill="#FF4D4D4D" Data="F1 M 7.56516,415.569C 7.56516,415.569 16.1558,354.061 57.0292,403.663L 40.7585,409.219C 40.7585,409.219 21.7118,380.649 26.4732,416.362L 7.56516,415.569 Z "/>
<Path Width="49.464" Height="32.031" Canvas.Left="209.585" Canvas.Top="386.712" Stretch="Fill" Fill="#FF4D4D4D" Data="F1 M 259.049,417.949C 259.049,417.949 250.458,356.441 209.585,406.044L 225.856,411.6C 225.856,411.6 244.902,383.029 240.141,418.743L 259.049,417.949 Z "/>
<Path Width="52.7105" Height="78.8311" Canvas.Left="207.962" Canvas.Top="315.965" Stretch="Fill" Fill="#FFFBB03B" Data="F1 M 241.764,315.965C 241.764,315.965 272.907,360.709 255.256,394.537C 254.187,396.587 229.463,385.807 229.463,385.807C 229.463,385.807 245.192,347.7 207.962,321.515L 241.764,315.965 Z "/>
<Path Width="52.7105" Height="78.8311" Canvas.Left="7.56529" Canvas.Top="315.965" Stretch="Fill" Fill="#FFFBB03B" Data="F1 M 26.4732,315.965C 26.4732,315.965 -4.6695,360.709 12.9812,394.537C 14.0505,396.587 38.7745,385.807 38.7745,385.807C 38.7745,385.807 23.0452,347.7 60.2758,321.515L 26.4732,315.965 Z "/>
<Path Width="124.603" Height="117.204" Canvas.Left="71.3145" Canvas.Top="323.364" Stretch="Fill" Fill="#FF0071BC" Data="F1 M 71.3145,323.364L 83.6158,440.568L 183.616,440.568L 195.917,323.364C 195.917,323.364 138.378,339.89 71.3145,323.364 Z "/>
<Path Width="60.7147" Height="60.7147" Canvas.Left="101.215" Canvas.Top="345.15" Stretch="Fill" Fill="#FF29ABE2" Data="F1 M 161.93,375.508C 161.93,392.273 148.338,405.865 131.572,405.865C 114.807,405.865 101.215,392.273 101.215,375.508C 101.215,358.742 114.807,345.15 131.572,345.15C 148.338,345.15 161.93,358.742 161.93,375.508 Z "/>
<Path Width="55.7173" Height="52.9907" Canvas.Left="103.714" Canvas.Top="346.345" Stretch="Fill" Fill="#FFFBB03B" Data="F1 M 131.572,346.345L 140.182,363.789L 159.431,366.587L 145.502,380.164L 148.79,399.336L 131.572,390.284L 114.355,399.336L 117.643,380.164L 103.714,366.587L 122.963,363.789L 131.572,346.345 Z "/>
<Rectangle Width="56.3893" Height="60.3174" Canvas.Left="105.541" Canvas.Top="440.569" Stretch="Fill" Fill="#FF333333"/>
<Path Width="134.529" Height="40.6529" Canvas.Left="66.5504" Canvas.Top="499.122" Stretch="Fill" Fill="#FF333333" Data="F1 M 66.5526,539.775C 66.5526,539.775 65.5606,504.855 105.541,500.886C 145.521,496.918 161.93,500.886 161.93,500.886C 161.93,500.886 201.473,508.028 201.077,539.775L 66.5526,539.775 Z "/>
<Viewbox Width="124.41" Height="43.5173" Canvas.Left="71.3869" Canvas.Top="500.618">
<Canvas Width="124.41" Height="43.5173">
<Path Width="24.3267" Height="24.3253" Canvas.Left="6.00001" Canvas.Top="13.1917" Stretch="Fill" StrokeThickness="4" StrokeMiterLimit="2.75" Stroke="#FFFFFFFF" Data="F1 M 28.3267,25.3544C 28.3267,30.9677 23.776,35.5171 18.164,35.5171C 12.5507,35.5171 8.00001,30.9677 8.00001,25.3544C 8.00001,19.7411 12.5507,15.1917 18.164,15.1917C 23.776,15.1917 28.3267,19.7411 28.3267,25.3544 Z "/>
<Path Width="24.3267" Height="24.3253" Canvas.Left="94.0832" Canvas.Top="13.1917" Stretch="Fill" StrokeThickness="4" StrokeMiterLimit="2.75" Stroke="#FFFFFFFF" Data="F1 M 116.41,25.3544C 116.41,30.9677 111.859,35.5171 106.247,35.5171C 100.634,35.5171 96.0832,30.9677 96.0832,25.3544C 96.0832,19.7411 100.634,15.1917 106.247,15.1917C 111.859,15.1917 116.41,19.7411 116.41,25.3544 Z "/>
<Path Width="30.12" Height="31.5173" Canvas.Left="63.2768" Canvas.Top="6" Stretch="Fill" StrokeThickness="4" StrokeMiterLimit="2.75" Stroke="#FFFFFFFF" Data="F1 M 91.3968,21.7586C 91.3968,29.3573 85.5501,35.5173 78.3368,35.5173C 71.1248,35.5173 65.2768,29.3573 65.2768,21.7586C 65.2768,14.16 71.1248,8 78.3368,8C 85.5501,8 91.3968,14.16 91.3968,21.7586 Z "/>
<Path Width="30.12" Height="31.5173" Canvas.Left="31.7417" Canvas.Top="6" Stretch="Fill" StrokeThickness="4" StrokeMiterLimit="2.75" Stroke="#FFFFFFFF" Data="F1 M 59.8617,21.7586C 59.8617,29.3573 54.0155,35.5173 46.8017,35.5173C 39.5897,35.5173 33.7417,29.3573 33.7417,21.7586C 33.7417,14.16 39.5897,8 46.8017,8C 54.0155,8 59.8617,14.16 59.8617,21.7586 Z "/>
</Canvas>
</Viewbox>
<Path Width="70.9805" Height="89.1187" Canvas.Left="129.646" Canvas.Top="126.318" Stretch="Fill" Fill="#FFFFFFFF" Data="F1 M 200.414,176.339C 200.414,204.389 203.636,215.437 185.015,215.437C 166.394,215.437 130.124,205.922 130.124,177.873C 130.124,149.823 125.623,126.318 144.244,126.318C 162.866,126.318 200.414,148.29 200.414,176.339 Z "/>
<Path Width="14.3283" Height="20.0774" Canvas.Left="137.081" Canvas.Top="178.087" Stretch="Fill" Fill="#FF000000" Data="F1 M 150.829,186.243C 152.386,191.688 150.7,196.945 147.064,197.985C 143.428,199.025 139.217,195.454 137.661,190.009C 136.104,184.565 137.789,179.307 141.426,178.267C 145.062,177.228 149.272,180.799 150.829,186.243 Z "/>
<Path Width="46.38" Height="59.5094" Canvas.Left="72.898" Canvas.Top="152.478" Stretch="Fill" Fill="#FFFFFFFF" Data="F1 M 72.898,188.126C 72.898,207.814 78.0433,211.988 87.4633,211.988C 96.8846,211.988 119.278,207.814 119.278,188.126C 119.278,168.438 111.642,152.478 102.221,152.478C 92.8006,152.478 72.898,168.438 72.898,188.126 Z "/>
<Path Width="14.3283" Height="20.0774" Canvas.Left="99.7244" Canvas.Top="181.554" Stretch="Fill" Fill="#FF000000" Data="F1 M 100.304,189.71C 98.7472,195.154 100.434,200.411 104.07,201.451C 107.706,202.491 111.916,198.92 113.472,193.475C 115.03,188.031 113.344,182.774 109.707,181.734C 106.071,180.694 101.862,184.266 100.304,189.71 Z "/>
<Path Width="43.8227" Height="14.2243" Canvas.Left="111.42" Canvas.Top="84.6779" Stretch="Fill" Fill="#FF0071BC" Data="F1 M 111.42,97.953C 111.42,97.953 132.179,67.4609 155.243,98.9023L 111.42,98.9023"/>
<Path Width="11.2907" Height="83.936" Canvas.Left="126.761" Canvas.Top="2.49296" Stretch="Fill" StrokeThickness="2.66667" StrokeMiterLimit="2.75" Stroke="#FF000000" Data="F1 M 133.332,85.0956L 132.724,71.2969L 128.094,72.6382L 136.718,57.8809L 130.124,56.5396L 136.718,44.6569L 128.094,44.6569L 136.718,26.4489L 128.094,27.2156L 133.616,3.82629"/>
<TextBlock TextAlignment="Center" Width="Auto" Height="Auto" Canvas.Left="0" Canvas.Top="0">
<TextBlock.RenderTransform>
<TransformGroup>
<MatrixTransform Matrix="1.33333,0,0,1.33333,15.72,548.133"/>
</TransformGroup>
</TextBlock.RenderTransform>
<Run FontFamily="Cooper Black" FontSize="28" Text="FunnyRobot" Foreground="#FF5A0FC8" Background="LightGreen"/>
</TextBlock>
</Canvas>
</Canvas>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment