Commit 659ec04b authored by hhchaos's avatar hhchaos

添加项目文件。

parent 78d64b97
Pipeline #157 canceled with stages
using System;
using System.Numerics;
using Windows.Foundation;
using Microsoft.Graphics.Canvas;
namespace SvgConverter
{
public abstract class AnimationBase : IDisposable
{
public Rect ViewBox { get; protected set; }
public abstract float Progress { get; set; }
public CanvasDevice Device { get; protected set; }
public abstract void Dispose();
public abstract Vector2? Draw(
CanvasDrawingSession drawingSession, float drawProgress);
}
}
\ No newline at end of file
Busing System.Reflection;
<?xml version="1.0" encoding="utf-8"?>
<!--
此文件包含运行时指令,应用程序通过反射和其他动态代码模式
所访问的类型的规范。运行时指令用于控制
.NET Native 优化器,并确保它不会删除你的库所访问的代码。如果你的
库不进行任何反射,那么一般而言你无需编辑此文件。但是,
如果你的库反射类型,尤其是传递到它或从它的类型所派生的类型,
那么就应该编写运行时指令。
库中反射最常见的使用方式是发现传递到库的
类型的信息。运行时指令有三种方式来表达传递给库的
类型的要求
1. Parameter、GenericParameter、TypeParameter、TypeEnumerableParameter
使用这些指令可反射作为参数传递的类型。
2. SubTypes
使用 SubTypes 指令反射从其他类型派生的类型。
3. AttributeImplies
使用 AttributeImplies 指令指示你的库需要反射使用
属性修饰的类型或方法。
有关为库编写运行时指令的详细信息,请参阅
https://go.microsoft.com/fwlink/?LinkID=391919
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="SvgConverter">
<!--在此处为库添加指令-->
</Library>
</Directives>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SvgConverter</RootNamespace>
<AssemblyName>SvgConverter</AssemblyName>
<DefaultLanguage>zh-CN</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.15063.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10586.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="AnimationBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SvgParseForWin2D\Utilities\SvgDrawHelper.cs" />
<Compile Include="SvgParseForWin2D\Win2DSvgElement.cs" />
<Compile Include="SvgParseForWin2D\Win2DSvgGeometry.cs" />
<Compile Include="SvgParseForWin2D\Win2DSvgImage.cs" />
<Compile Include="SvgParseForWin2D\Win2DSvgNode.cs" />
<Compile Include="SvgParseForWin2D\Utilities\Win2DSvgParseHelper.cs" />
<Compile Include="SvgParse\Attributes\DisplayMode.cs" />
<Compile Include="SvgParse\Attributes\TextAnchor.cs" />
<Compile Include="SvgParse\Brushes\ISvgBrush.cs" />
<Compile Include="SvgParse\Brushes\SvgGradientStop.cs" />
<Compile Include="SvgParse\Brushes\SvgLinearGradientBrush.cs" />
<Compile Include="SvgParse\Brushes\SvgRadialGradientBrush.cs" />
<Compile Include="SvgParse\Brushes\SvgSolidColorBrush.cs" />
<Compile Include="SvgParse\SvgAttributesHelper\SvgColorHelper.cs" />
<Compile Include="SvgParse\SvgAttributesHelper\SvgLengthHelper.cs" />
<Compile Include="SvgParse\SvgAttributesHelper\SvgTransformHelper.cs" />
<Compile Include="SvgParse\SvgAttributesHelper\SvgBrushHelper.cs" />
<Compile Include="SvgParse\SvgElement.cs" />
<Compile Include="SvgParse\SvgGeometry.cs" />
<Compile Include="SvgParse\SvgImage.cs" />
<Compile Include="SvgParse\SvgNode.cs" />
<Compile Include="SvgParse\SvgNodeGroup.cs" />
<Compile Include="SvgParse\SvgNodeStyle.cs" />
<Compile Include="SvgParse\Utilities\SvgParseHelper.cs" />
<Compile Include="SvgParse\SvgRectangle.cs" />
<Compile Include="SvgParse\SvgText.cs" />
<Compile Include="SvgParse\Utilities\SvgDefsNodeHelper.cs" />
<Compile Include="SvgParse\Utilities\SvgLoadHelper.cs" />
<Compile Include="TextParse\PathMoveDirection.cs" />
<Compile Include="TextParse\PathPoint.cs" />
<Compile Include="TextParse\CharGeometry.cs" />
<Compile Include="TextParse\TextSvgElement.cs" />
<Compile Include="TextParse\TextParseHelper.cs" />
<Compile Include="TextParse\Win2DCharSvgElement.cs" />
<EmbeddedResource Include="Properties\SvgConverter.rd.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.0.1</Version>
</PackageReference>
<PackageReference Include="Win2D.uwp">
<Version>1.21.0</Version>
</PackageReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29020.237
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SvgConverter", "SvgConverter.csproj", "{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Debug|Any CPU.Build.0 = Debug|Any CPU
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Debug|ARM.ActiveCfg = Debug|ARM
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Debug|ARM.Build.0 = Debug|ARM
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Debug|x64.ActiveCfg = Debug|x64
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Debug|x64.Build.0 = Debug|x64
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Debug|x86.ActiveCfg = Debug|x86
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Debug|x86.Build.0 = Debug|x86
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Release|Any CPU.ActiveCfg = Release|Any CPU
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Release|Any CPU.Build.0 = Release|Any CPU
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Release|ARM.ActiveCfg = Release|ARM
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Release|ARM.Build.0 = Release|ARM
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Release|x64.ActiveCfg = Release|x64
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Release|x64.Build.0 = Release|x64
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Release|x86.ActiveCfg = Release|x86
{500B15E8-7089-4EB2-BFF5-4FEAAC44BA56}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {39C58346-1BD7-484B-B331-352CC4626934}
EndGlobalSection
EndGlobal
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SvgConverter.SvgParse.Attributes
{
public enum DisplayMode
{
Inline,
None,
Other
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SvgConverter.SvgParse.Attributes
{
public enum TextAnchor
{
Start,
Middle,
End
}
}
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
namespace SvgConverter.SvgParse.Brushes
{
public interface ISvgBrush
{
float Opacity { get; set; }
Matrix3x2 Transform { get; set; }
ICanvasBrush Parse(ICanvasResourceCreator resourceCreator);
}
}
\ No newline at end of file
using Windows.UI;
namespace SvgConverter.SvgParse.Brushes
{
public struct SvgGradientStop
{
//
// 摘要:
// The position of the gradient stop. Expected to be between 0 and 1, inclusive.
public float Position;
public Color Color;
}
}
\ No newline at end of file
using System.Linq;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
namespace SvgConverter.SvgParse.Brushes
{
public class SvgLinearGradientBrush : ISvgBrush
{
public SvgLinearGradientBrush(SvgGradientStop[] gradientStops)
{
Stops = gradientStops;
}
public SvgGradientStop[] Stops { get; }
//
// 摘要:
// The point on the canvas on which the gradient starts.
public Vector2 StartPoint { get; set; }
//
// 摘要:
// The point on the canvas on which the gradient stops.
public Vector2 EndPoint { get; set; }
public float Opacity { get; set; } = 1;
public Matrix3x2 Transform { get; set; }
public ICanvasBrush Parse(ICanvasResourceCreator resourceCreator)
{
var stops = Stops.Select(o => new CanvasGradientStop
{
Position = o.Position,
Color = o.Color
});
var linearGra = new CanvasLinearGradientBrush(resourceCreator, stops.ToArray())
{
StartPoint = StartPoint,
EndPoint = EndPoint,
Transform = Transform,
Opacity = Opacity
};
return linearGra;
}
}
}
\ No newline at end of file
using System.Linq;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
namespace SvgConverter.SvgParse.Brushes
{
public class SvgRadialGradientBrush : ISvgBrush
{
public SvgRadialGradientBrush(SvgGradientStop[] gradientStops)
{
Stops = gradientStops;
}
public SvgGradientStop[] Stops { get; }
//
// 摘要:
// Specifies the vertical radius of the brush's radial gradient.
public float RadiusY { get; set; }
//
// 摘要:
// Specifies the horizontal radius of the brush's radial gradient.
public float RadiusX { get; set; }
//
// 摘要:
// Specifies a displacement from Center, used to form the brush's radial gradient.
public Vector2 OriginOffset { get; set; }
//
// 摘要:
// Specifies the center of the brush's radial gradient
public Vector2 Center { get; set; }
public float Opacity { get; set; } = 1;
public Matrix3x2 Transform { get; set; }
public ICanvasBrush Parse(ICanvasResourceCreator resourceCreator)
{
var stops = Stops.Select(o => new CanvasGradientStop
{
Position = o.Position,
Color = o.Color
});
var radialGra = new CanvasRadialGradientBrush(resourceCreator, stops.ToArray())
{
Center = Center,
OriginOffset = OriginOffset,
RadiusX = RadiusX,
RadiusY = RadiusY,
Transform = Transform,
Opacity = Opacity
};
return radialGra;
}
}
}
\ No newline at end of file
using System.Numerics;
using Windows.UI;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
namespace SvgConverter.SvgParse.Brushes
{
public class SvgSolidColorBrush : ISvgBrush
{
public SvgSolidColorBrush(Color color)
{
Color = color;
}
public Color Color { get; set; }
public float Opacity { get; set; } = 1;
public Matrix3x2 Transform { get; set; }
public ICanvasBrush Parse(ICanvasResourceCreator resourceCreator)
{
return new CanvasSolidColorBrush(resourceCreator, Color)
{
Opacity = Opacity
};
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Numerics;
using System.Xml;
using Windows.Foundation;
using Windows.UI;
using SvgConverter.SvgParse.Brushes;
namespace SvgConverter.SvgParse.SvgAttributesHelper
{
public static class SvgBrushHelper
{
public static ISvgBrush Parse(string brush, Dictionary<string, ISvgBrush> defBrushes)
{
if (string.IsNullOrWhiteSpace(brush) || brush.ToLower().Equals("none"))
return new SvgSolidColorBrush(Colors.Transparent);
if (brush.StartsWith("url(") && defBrushes != null)
{
brush =
brush.Replace("url(", string.Empty)
.Replace("#", string.Empty)
.Replace(")", string.Empty)
.Replace(" ", string.Empty);
if (defBrushes.ContainsKey(brush)) return defBrushes[brush];
return new SvgSolidColorBrush(Colors.Transparent);
}
return new SvgSolidColorBrush(SvgColorHelper.ParseColor(brush));
}
public static SvgLinearGradientBrush ParseLinearGradientBrush(XmlElement brush, Size refSize)
{
if (brush != null && brush.Name == "linearGradient")
{
var stopList = brush.GetElementsByTagName("stop");
var list = new List<SvgGradientStop>();
foreach (XmlNode item in stopList)
{
var offset = SvgLengthHelper.ParseLength(item.Attributes["offset"]?.Value, 1);
var styles = ParseStyle(item.Attributes);
if (styles != null)
{
styles.TryGetValue("stop-color", out var stopColorStr);
var color = string.IsNullOrWhiteSpace(stopColorStr)
? Colors.Black
: SvgColorHelper.ParseColor(stopColorStr);
if (styles.TryGetValue("stop-opacity", out var stopOpacityStr))
color.A = (byte) (SvgLengthHelper.ParseLength(stopOpacityStr, 1) * 255);
list.Add(new SvgGradientStop
{
Position = (float) offset,
Color = color
});
}
}
if (list.Count == 0)
return null;
var linearGra = new SvgLinearGradientBrush(list.ToArray())
{
StartPoint =
new Point(SvgLengthHelper.ParseLength(brush.Attributes["x1"]?.Value, refSize.Width),
SvgLengthHelper.ParseLength(brush.Attributes["y1"]?.Value, refSize.Height)).ToVector2(),
EndPoint =
new Point(
SvgLengthHelper.ParseLength(
brush.Attributes["x2"] == null ? "100%" : brush.Attributes["x2"]?.Value, refSize.Width),
SvgLengthHelper.ParseLength(brush.Attributes["y2"]?.Value, refSize.Height)).ToVector2(),
Transform = SvgTransformHelper.ParseTransform(brush.Attributes["gradientTransform"]?.Value)
};
//if (brush.Attributes["gradientUnits"]?.Value != "userSpaceOnUse")
//{
// linearGra.StartPoint =
// new Point(linearGra.StartPoint.X * refSize.Width, linearGra.StartPoint.Y * refSize.Height)
// .ToVector2();
// linearGra.EndPoint =
// new Point(linearGra.EndPoint.X * refSize.Width, linearGra.EndPoint.Y * refSize.Height)
// .ToVector2();
//}
return linearGra;
}
return null;
}
public static SvgRadialGradientBrush ParseRadialGradientBrush(XmlElement brush, Size refSize)
{
if (brush != null && brush.Name == "radialGradient")
{
var stopList = brush.GetElementsByTagName("stop");
var list = new List<SvgGradientStop>();
foreach (XmlNode item in stopList)
{
var offset = SvgLengthHelper.ParseLength(item.Attributes["offset"]?.Value, 1);
var styles = ParseStyle(item.Attributes);
if (styles != null)
{
styles.TryGetValue("stop-color", out var stopColorStr);
var color = string.IsNullOrWhiteSpace(stopColorStr)
? Colors.Black
: SvgColorHelper.ParseColor(stopColorStr);
if (styles.TryGetValue("stop-opacity", out var stopOpacityStr))
color.A = (byte) (SvgLengthHelper.ParseLength(stopOpacityStr, 1) * 255);
list.Add(new SvgGradientStop
{
Position = (float) offset,
Color = color
});
}
}
if (list.Count == 0)
return null;
var radialGra = new SvgRadialGradientBrush(list.ToArray())
{
Center =
new Point(
SvgLengthHelper.ParseLength(
brush.Attributes["cx"] == null ? "50%" : brush.Attributes["cx"]?.Value,
refSize.Width),
SvgLengthHelper.ParseLength(
brush.Attributes["cy"] == null ? "50%" : brush.Attributes["cy"]?.Value,
refSize.Height))
.ToVector2(),
OriginOffset = new Point(SvgLengthHelper.ParseLength(brush.Attributes["fx"]?.Value, refSize.Width),
SvgLengthHelper.ParseLength(brush.Attributes["fy"]?.Value, refSize.Height)).ToVector2(),
RadiusX =
(float)
SvgLengthHelper.ParseLength(
brush.Attributes["r"] == null ? "50%" : brush.Attributes["r"]?.Value, refSize.Width),
RadiusY =
(float)
SvgLengthHelper.ParseLength(
brush.Attributes["r"] == null ? "50%" : brush.Attributes["r"]?.Value, refSize.Width),
Transform = SvgTransformHelper.ParseTransform(brush.Attributes["gradientTransform"]?.Value)
};
//if (brush.Attributes["gradientUnits"]?.Value != "userSpaceOnUse")
//{
// radialGra.Center =
// new Point(radialGra.Center.X * refSize.Width, radialGra.Center.Y * refSize.Height)
// .ToVector2();
// radialGra.OriginOffset =
// new Point(radialGra.OriginOffset.X * refSize.Width, radialGra.OriginOffset.Y * refSize.Height)
// .ToVector2();
// radialGra.RadiusX = radialGra.RadiusY = (float) (radialGra.RadiusX * refSize.Width);
//}
return radialGra;
}
return null;
}
private static Dictionary<string, string> ParseStyle(XmlAttributeCollection style)
{
if (style != null && style.Count > 0)
{
var dic = new Dictionary<string, string>();
foreach (XmlAttribute item in style)
if (item.Name == "style")
{
var strs = item.Value?.Split(';');
if (strs != null)
foreach (var str in strs)
{
var keyValue = str.Split(':');
if (keyValue?.Length == 2) dic[keyValue[0].Trim()] = keyValue[1].Trim();
}
}
else
{
dic[item.Name] = item.Value;
}
return dic;
}
return null;
}
}
}
\ No newline at end of file
This diff is collapsed.
namespace SvgConverter.SvgParse.SvgAttributesHelper
{
public static class SvgLengthHelper
{
/// <summary>
/// 转换svg中的长度单位(dpi=96,1em=16,1em=1ex)
/// </summary>
/// <param name="length"></param>
/// <param name="refLength"></param>
/// <returns></returns>
public static double ParseLength(string length, double refLength)
{
if (string.IsNullOrWhiteSpace(length))
return 0;
if (double.TryParse(length, out var result))
return result;
length = length.Replace(" ", string.Empty).ToLower();
if (length.Contains("px"))
return ParseLength(length.Replace("px", string.Empty), refLength);
if (length.Contains("%"))
return ParseLength(length.Replace("%", string.Empty), refLength) * refLength / 100;
if (length.Contains("pt"))
return ParseLength(length.Replace("pt", string.Empty), refLength) * 12 / 9;
if (length.Contains("pc"))
return ParseLength(length.Replace("pc", string.Empty), refLength) * 16;
if (length.Contains("em"))
return ParseLength(length.Replace("em", string.Empty), refLength) * 16;
if (length.Contains("ex"))
return ParseLength(length.Replace("ex", string.Empty), refLength) * 16;
if (length.Contains("cm"))
return ParseLength(length.Replace("cm", string.Empty), refLength) * 96 / 0.254;
if (length.Contains("mm"))
return ParseLength(length.Replace("mm", string.Empty), refLength) * 96 / 25.4;
if (length.Contains("in")) return ParseLength(length.Replace("in", string.Empty), refLength) * 96;
return 0;
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text.RegularExpressions;
namespace SvgConverter.SvgParse.SvgAttributesHelper
{
public static class SvgTransformHelper
{
public static Matrix3x2 ParseTransform(string transform)
{
if (string.IsNullOrWhiteSpace(transform))
return Matrix3x2.Identity;
transform = transform.Replace(',', ' ');
transform = Regex.Replace(transform, @"\s+", " ");
var transStrList = new List<string>();
do
{
if (char.IsLower(transform[0]))
{
var end = transform.IndexOf(')');
transStrList.Add(transform.Substring(0, end + 1));
transform = transform.Substring(end + 1);
}
else
{
transform = transform.Substring(1);
}
} while (transform.Length > 0);
var result = Matrix3x2.Identity;
foreach (var trans in transStrList)
{
var m = Matrix3x2.Identity;
var str = trans.Trim();
if (str.StartsWith("translate"))
{
str = str.Substring(10, str.Length - 11);
m = GetTranslate(str);
}
else if (str.StartsWith("scale"))
{
str = str.Substring(6, str.Length - 7);
m = GetScale(str);
}
else if (str.StartsWith("rotate"))
{
str = str.Substring(7, str.Length - 8);
m = GetRotate(str);
}
else if (str.StartsWith("skewX"))
{
str = str.Substring(6, str.Length - 7);
if (float.TryParse(str.Trim(), out var angle))
m = Matrix3x2.CreateSkew(angle, 0);
else
continue;
}
else if (str.StartsWith("skewY"))
{
str = str.Substring(6, str.Length - 7);
if (float.TryParse(str.Trim(), out var angle))
m = Matrix3x2.CreateSkew(0, angle);
else
continue;
}
else if (str.StartsWith("matrix"))
{
str = str.Substring(7, str.Length - 8);
m = GetMatrix(str);
}
result = m * result;
}
return result;
}
private static Matrix3x2 GetMatrix(string transform)
{
var strs = transform.Split(' ');
if (strs.Length != 6)
return Matrix3x2.Identity;
float.TryParse(strs[0].Trim(), out var a);
float.TryParse(strs[1].Trim(), out var b);
float.TryParse(strs[2].Trim(), out var c);
float.TryParse(strs[3].Trim(), out var d);
float.TryParse(strs[4].Trim(), out var e);
float.TryParse(strs[5].Trim(), out var f);
return new Matrix3x2(a, b, c, d, e, f);
}
private static Matrix3x2 GetTranslate(string transform)
{
var strs = transform.Split(' ');
if (!(strs.Length > 0))
return Matrix3x2.Identity;
float.TryParse(strs[0].Trim(), out var x);
if (strs.Length <= 1)
return Matrix3x2.CreateTranslation(new Vector2(x, 0));
float.TryParse(strs[1].Trim(), out var y);
return Matrix3x2.CreateTranslation(new Vector2(x, y));
}
private static Matrix3x2 GetScale(string transform)
{
var strs = transform.Split(' ');
if (!(strs.Length > 0))
return Matrix3x2.Identity;
float.TryParse(strs[0].Trim(), out var x);
if (strs.Length <= 1)
return Matrix3x2.CreateScale(x);
float.TryParse(strs[1].Trim(), out var y);
return Matrix3x2.CreateScale(x, y);
}
private static Matrix3x2 GetRotate(string transform)
{
var strs = transform.Split(' ');
if (strs.Length == 0)
return Matrix3x2.Identity;
float.TryParse(strs[0].Trim(), out var angle);
angle *= (float) Math.PI / 180;
if (strs.Length < 3) return Matrix3x2.CreateRotation(angle);
float.TryParse(strs[1].Trim(), out var x);
float.TryParse(strs[2].Trim(), out var y);
return Matrix3x2.CreateRotation(angle, new Vector2(x, y));
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using Windows.Foundation;
using SvgConverter.SvgParse.Brushes;
using SvgConverter.SvgParse.SvgAttributesHelper;
using SvgConverter.SvgParse.Utilities;
namespace SvgConverter.SvgParse
{
public class SvgElement
{
public Dictionary<string, SvgNodeStyle> CssStyles { get; private set; }
public Dictionary<string, ISvgBrush> DefBrushes { get; private set; }
public Dictionary<string, SvgNodeGroup> DefClipPath { get; private set; }
public Dictionary<string, SvgNode> DefSvgNodes { get; private set; }
public Rect ViewBox => new Rect(Offset, Size);
public Point Offset { get; private set; }
public Size Size { get; private set; }
public List<SvgNode> Children { get; } = new List<SvgNode>();
private static Rect GetRect(string xml)
{
if (string.IsNullOrWhiteSpace(xml))
return new Rect();
var strs = xml.Split(' ');
if (strs.Length == 4)
{
var x = SvgLengthHelper.ParseLength(strs[0], 0);
var y = SvgLengthHelper.ParseLength(strs[1], 0);
var width = SvgLengthHelper.ParseLength(strs[2], 0);
var height = SvgLengthHelper.ParseLength(strs[3], 0);
return new Rect(new Point(x, y), new Size(width, height));
}
return new Rect();
}
private void ParseBaseStyle(Dictionary<string, string> dic)
{
if (dic == null) return;
foreach (var item in dic)
switch (item.Key.ToLower())
{
case "viewbox":
var viewBox = GetRect(item.Value);
Offset = new Point(viewBox.X, viewBox.Y);
Size = new Size(viewBox.Width, viewBox.Height);
break;
case "width":
Size = new Size(SvgLengthHelper.ParseLength(item.Value, Size.Width), Size.Height);
break;
case "height":
Size = new Size(Size.Width, SvgLengthHelper.ParseLength(item.Value, Size.Height));
break;
case "x":
case "top":
Offset = new Point(Offset.X, SvgLengthHelper.ParseLength(item.Value, 0));
break;
case "y":
case "left":
Offset = new Point(SvgLengthHelper.ParseLength(item.Value, 0), Offset.Y);
break;
case "style":
var styleDic = new Dictionary<string, string>();
var strs = item.Value.Split(';');
foreach (var str in strs)
{
var keyValue = str.Split(':');
if (keyValue?.Length == 2) styleDic[keyValue[0].Trim()] = keyValue[1].Trim();
}
ParseBaseStyle(styleDic);
break;
}
}
/// <summary>
/// 从xml字符串中加载svg文档
/// </summary>
/// <param name="xml"></param>
/// <returns></returns>
public static SvgElement LoadFromXml(string xml)
{
var svg = new SvgElement();
var xmlDoc = new XmlDocument();
var settings = new XmlReaderSettings
{
DtdProcessing = DtdProcessing.Ignore,
IgnoreComments = true,
IgnoreProcessingInstructions = true,
IgnoreWhitespace = true
};
xml = Regex.Replace(xml, @"\s+", " ");
var str = xml.Replace("&ns_extend;", "http://ns.adobe.com/Extensibility/1.0/")
.Replace("&ns_ai;", "http://ns.adobe.com/AdobeIllustrator/10.0/")
.Replace("&ns_graphs;", "http://ns.adobe.com/Graphs/1.0/")
.Replace("&ns_vars;", "http://ns.adobe.com/Variables/1.0/")
.Replace("&ns_imrep;", "http://ns.adobe.com/ImageReplacement/1.0/")
.Replace("&ns_sfw;", "http://ns.adobe.com/SaveForWeb/1.0/")
.Replace("&ns_custom;", "http://ns.adobe.com/GenericCustomNamespace/1.0/")
.Replace("&ns_adobe_xpath;", "http://ns.adobe.com/XPath/1.0/")
.Replace("<switch", "<g")
.Replace("</switch", "</g");
var reader = XmlReader.Create(new StringReader(str), settings);
xmlDoc.Load(reader);
var root = xmlDoc.DocumentElement;
if (root.Name.ToLower().Equals("svg") && root.HasChildNodes)
{
var dic = new Dictionary<string, string>();
foreach (XmlAttribute item in root.Attributes) dic[item.Name] = item.Value;
svg.ParseBaseStyle(dic);
if (svg.Size == new Size())
svg.Size = new Size(500, 500);
svg.DefBrushes = SvgDefsNodeHelper.GetDefBrushes(root, svg.Size);
svg.DefSvgNodes = SvgDefsNodeHelper.GetDefSvgNodes(root, svg.DefBrushes, svg.Size);
svg.DefClipPath = SvgDefsNodeHelper.GetDefClipPath(root, svg.DefSvgNodes, svg.Size);
svg.CssStyles = SvgDefsNodeHelper.GetCssStyles(root, svg.DefBrushes, svg.DefClipPath, svg.Size);
var ele = root.FirstChild;
while (ele != null)
{
if (ele.NodeType == XmlNodeType.Element)
switch (ele.Name.ToLower())
{
case "g":
var group = SvgLoadHelper.GetGeometryGroupFromXml(ele, svg.CssStyles, svg.DefBrushes,
svg.Size, svg.DefSvgNodes, svg.DefClipPath);
if (group != null)
svg.Children.Add(group);
break;
default:
var geo = SvgLoadHelper.GetGeometryFromXml(ele, svg.CssStyles, svg.DefBrushes,
svg.Size, svg.DefSvgNodes, svg.DefClipPath);
if (geo != null)
svg.Children.Add(geo);
break;
}
ele = ele.NextSibling;
}
}
return svg;
}
}
}
\ No newline at end of file
using Windows.UI.Xaml.Media;
namespace SvgConverter.SvgParse
{
public class SvgGeometry : SvgNode
{
public Geometry Geometry { get; set; }
public override SvgNode Clone()
{
var cloneNode = new SvgGeometry()
{
RenderOpacity = RenderOpacity,
RenderTransform = RenderTransform,
Style = Style.Clone(),
Geometry = Geometry
};
return cloneNode;
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
namespace SvgConverter.SvgParse
{
public sealed class SvgImage : SvgNode
{
public static readonly List<string> Base64DateHeaders = new List<string>
{
"data:image/png;base64,",
"data:image/jpeg;base64,",
"data:image/jpg;base64,",
"data:image/x-icon;base64,"
};
public Rect ViewRect { get; set; }
public byte[] ImageBytes { get; set; }
public async Task<ImageSource> GetImageSource()
{
if (ImageBytes == null) return null;
var img = new BitmapImage();
using (var randomAccessStream = new InMemoryRandomAccessStream())
{
var buffer = CryptographicBuffer.CreateFromByteArray(ImageBytes);
await randomAccessStream.WriteAsync(buffer);
randomAccessStream.Seek(0);
await img.SetSourceAsync(randomAccessStream);
}
return img;
}
public override SvgNode Clone()
{
var cloneNode = new SvgImage()
{
RenderOpacity = RenderOpacity,
RenderTransform = RenderTransform,
Style = Style.Clone(),
ViewRect = ViewRect,
ImageBytes = ImageBytes
};
return cloneNode;
}
}
}
\ No newline at end of file
using System.Numerics;
namespace SvgConverter.SvgParse
{
public abstract class SvgNode
{
public string Id { get; set; }
public double RenderOpacity { get; set; } = 1;
public Matrix3x2 RenderTransform { get; set; } = Matrix3x2.Identity;
public SvgNodeStyle Style { get; set; } = new SvgNodeStyle();
public abstract SvgNode Clone();
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
namespace SvgConverter.SvgParse
{
public class SvgNodeGroup : SvgNode
{
public List<SvgNode> Children { get; private set; } = new List<SvgNode>();
public override SvgNode Clone()
{
var cloneNode = new SvgNodeGroup()
{
RenderOpacity = RenderOpacity,
RenderTransform = RenderTransform,
Style = Style.Clone(),
Children = Children.Select(o => o.Clone()).ToList()
};
return cloneNode;
}
}
}
\ No newline at end of file
This diff is collapsed.
using Windows.Foundation;
namespace SvgConverter.SvgParse
{
public class SvgRectangle : SvgNode
{
public Rect Rect { get; set; }
public float RadiusX { get; set; }
public float RadiusY { get; set; }
public override SvgNode Clone()
{
var cloneNode = new SvgRectangle()
{
RenderOpacity = RenderOpacity,
RenderTransform = RenderTransform,
Style = Style.Clone(),
Rect = Rect,
RadiusX = RadiusX,
RadiusY = RadiusY
};
return cloneNode;
}
}
}
\ No newline at end of file
using Windows.Foundation;
using SvgConverter.SvgParse.Attributes;
namespace SvgConverter.SvgParse
{
public class SvgText : SvgNode
{
public Point Position { get; set; }
public string Content { get; set; }
public double FontSize { get; set; }
public string FontFamily { get; set; }
public TextAnchor TextAnchor { get; set; }
public override SvgNode Clone()
{
var cloneNode = new SvgText()
{
RenderOpacity = RenderOpacity,
RenderTransform = RenderTransform,
Style = Style.Clone(),
Position = Position,
Content = Content,
FontSize = FontSize,
FontFamily = FontFamily,
TextAnchor = TextAnchor
};
return cloneNode;
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Xml;
using Windows.Foundation;
using SvgConverter.SvgParse.Brushes;
using SvgConverter.SvgParse.SvgAttributesHelper;
namespace SvgConverter.SvgParse.Utilities
{
public static class SvgDefsNodeHelper
{
public static Dictionary<string, ISvgBrush> GetDefBrushes(XmlElement xmlElement, Size refSize)
{
var defBrushes = new Dictionary<string, ISvgBrush>();
var linearBrushList = xmlElement.GetElementsByTagName("linearGradient");
foreach (XmlElement item in linearBrushList)
{
var id = item.Attributes["id"]?.Value;
if (!string.IsNullOrWhiteSpace(id))
{
var brush = SvgBrushHelper.ParseLinearGradientBrush(item, refSize);
if (brush != null)
defBrushes[id] = brush;
}
}
var radialBrushList = xmlElement.GetElementsByTagName("radialGradient");
foreach (XmlElement item in radialBrushList)
{
var id = item.Attributes["id"]?.Value;
if (!string.IsNullOrWhiteSpace(id))
{
var brush = SvgBrushHelper.ParseRadialGradientBrush(item, refSize);
if (brush != null)
defBrushes[id] = brush;
}
}
return defBrushes;
}
public static Dictionary<string, SvgNodeStyle> GetCssStyles(XmlElement xmlElement,
Dictionary<string, ISvgBrush> defBrushes, Dictionary<string, SvgNodeGroup> defClipPath, Size refSize)
{
var cssStyles = new Dictionary<string, SvgNodeStyle>();
var styleList = xmlElement.GetElementsByTagName("style");
foreach (XmlNode item in styleList)
{
var styleStr = item.InnerText.Replace(" ", string.Empty)
.Replace("\n", string.Empty)
.Replace("\t", string.Empty);
if (!string.IsNullOrWhiteSpace(styleStr))
{
var styles = styleStr.Split('}');
foreach (var style in styles)
{
if (string.IsNullOrWhiteSpace(style)) continue;
var idEnd = style.IndexOf('{');
if (idEnd == -1) continue;
var keyString = style.Substring(0, idEnd);
var styleString = style.Substring(idEnd + 1);
if (keyString.Length > 1)
{
var keys = keyString.Split(',');
foreach (var keyItem in keys)
{
if (string.IsNullOrWhiteSpace(keyItem))
continue;
var key = keyItem.Trim().Substring(1);
if (cssStyles.ContainsKey(key))
{
cssStyles[key].MergeStyle(styleString, defBrushes, refSize, defClipPath);
}
else
{
var svgStyle = SvgNodeStyle.Parse(styleString, defBrushes, refSize, defClipPath);
cssStyles[key] = svgStyle;
}
}
}
}
}
}
return cssStyles;
}
public static Dictionary<string, SvgNodeGroup> GetDefClipPath(XmlElement xmlElement,
Dictionary<string, SvgNode> defNodes, Size refSize)
{
var defClipPath = new Dictionary<string, SvgNodeGroup>();
var clipPathList = xmlElement.GetElementsByTagName("clipPath");
foreach (XmlNode item in clipPathList)
{
var group = SvgLoadHelper.GetGeometryGroupFromXml(item, null, null, refSize, defNodes);
if (group?.Id != null)
defClipPath[group.Id] = group;
}
return defClipPath;
}
public static Dictionary<string, SvgNode> GetDefSvgNodes(XmlElement xmlElement,
Dictionary<string, ISvgBrush> defBrushes, Size refSize)
{
var defNodes = new Dictionary<string, SvgNode>();
var defNodeList = xmlElement.GetElementsByTagName("defs");
foreach (XmlNode item in defNodeList)
foreach (XmlNode ele in item.ChildNodes)
if (ele.NodeType == XmlNodeType.Element)
switch (ele.Name.ToLower())
{
case "g":
var group = SvgLoadHelper.GetGeometryGroupFromXml(ele, null, defBrushes,
refSize);
if (group?.Id != null)
defNodes[group.Id] = group;
break;
default:
var geo = SvgLoadHelper.GetGeometryFromXml(ele, null, defBrushes,
refSize);
if (geo?.Id != null)
defNodes[geo.Id] = geo;
break;
}
return defNodes;
}
}
}
\ No newline at end of file
This diff is collapsed.
using System.Collections.Generic;
namespace SvgConverter.SvgParse.Utilities
{
public static class SvgParseHelper
{
public static List<SvgNode> GetSvgGeometrys(SvgElement svg)
{
var list = new List<SvgNode>();
foreach (var item in svg.Children)
{
if (item.Style.Display == Attributes.DisplayMode.None)
continue;
item.RenderOpacity = item.Style.Opacity;
item.RenderTransform = item.Style.Transform;
if (item is SvgNodeGroup group)
list.AddRange(GetSvgGeometrys(group));
else
list.Add(item);
}
return list;
}
public static List<SvgNode> GetSvgGeometrys(SvgNodeGroup grop)
{
var list = new List<SvgNode>();
foreach (var item in grop.Children)
{
if (grop.Style?.ClipPath != null)
item.Style.ParentClipPath = grop.Style.ClipPath;
item.RenderOpacity = item.Style.Opacity * grop.RenderOpacity;
item.RenderTransform = item.Style.Transform * grop.RenderTransform;
if (item is SvgNodeGroup group)
list.AddRange(GetSvgGeometrys(group));
else
list.Add(item);
}
return list;
}
//public static async void Draw(List<SvgNode> items, Panel panel)
//{
// panel.Children.Clear();
// while (items.Count != 0)
// {
// var item = items[0];
// items.RemoveAt(0);
// if (item is SvgGeometry)
// {
// var geo = (SvgGeometry) item;
// var path = new Path()
// {
// Data = geo.Geometry,
// Opacity = geo.RenderOpacity,
// Stretch = geo.Style.Stretch,
// Stroke = geo.Style.Stroke,
// StrokeThickness = geo.Style.StrokeThickness,
// StrokeMiterLimit = geo.Style.StrokeMiterLimit,
// Fill = geo.Style.Fill,
// StrokeDashArray = geo.Style.StrokeDashArray,
// StrokeDashOffset = geo.Style.StrokeDashOffset,
// StrokeDashCap = geo.Style.StrokeLineCap,
// StrokeStartLineCap = geo.Style.StrokeLineCap,
// StrokeEndLineCap = geo.Style.StrokeLineCap,
// StrokeLineJoin = geo.Style.StrokeLineJoin
// };
// //path.RenderTransform = new MatrixTransform()
// //{
// // Matrix =
// // new Matrix(geo.RenderTransform.M11, geo.RenderTransform.M12,
// // geo.RenderTransform.M21, geo.RenderTransform.M22,
// // geo.RenderTransform.M31, geo.RenderTransform.M32)
// //};
// path.Data = geo.Geometry;
// panel.Children.Add(path);
// }
// else if (item is SvgRectangle)
// {
// var rect = (SvgRectangle)item;
// var rectangle = new Rectangle
// {
// Width = rect.Rect.Width,
// Height = rect.Rect.Height,
// Margin = new Thickness(rect.Rect.X, rect.Rect.Y, 0, 0),
// RadiusX = rect.radiusX,
// RadiusY = rect.radiusY,
// Opacity = rect.RenderOpacity,
// Stretch = rect.Style.Stretch,
// Stroke = rect.Style.Stroke,
// StrokeThickness = rect.Style.StrokeThickness,
// StrokeMiterLimit = rect.Style.StrokeMiterLimit,
// Fill = rect.Style.Fill,
// StrokeDashArray = rect.Style.StrokeDashArray,
// StrokeDashOffset = rect.Style.StrokeDashOffset,
// StrokeDashCap = rect.Style.StrokeLineCap,
// StrokeStartLineCap = rect.Style.StrokeLineCap,
// StrokeEndLineCap = rect.Style.StrokeLineCap,
// StrokeLineJoin = rect.Style.StrokeLineJoin
// };
// panel.Children.Add(rectangle);
// }
// else if (item is SvgImage)
// {
// var svgImg = (SvgImage) item;
// var img = new Image
// {
// Opacity = svgImg.RenderOpacity,
// Margin = new Thickness(svgImg.ViewRect.X, svgImg.ViewRect.Y, 0, 0),
// Width = svgImg.ViewRect.Width,
// Height = svgImg.ViewRect.Height,
// Source = await svgImg.GetImageSource()
// };
// //img.RenderTransform = new MatrixTransform()
// //{
// // Matrix =
// // new Matrix(svgImg.RenderTransform.M11, svgImg.RenderTransform.M12,
// // svgImg.RenderTransform.M21, svgImg.RenderTransform.M22,
// // svgImg.RenderTransform.M31, svgImg.RenderTransform.M32)
// //};
// panel.Children.Add(img);
// }
// }
//}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Graphics.Canvas.Geometry;
namespace SvgConverter.SvgParseForWin2D.Utilities
{
public static class SvgDrawHelper
{
public static CanvasStrokeStyle GetPartPathStyle(this Win2DSvgGeometry geo, float drawLength)
{
if (drawLength > geo.PathLength)
return geo.CanvasStrokeStyle;
var noneLength = geo.PathLength - drawLength + geo.StrokeThickness;
var actualDrawLength = drawLength / geo.StrokeThickness;
var actualNoneLength = noneLength / geo.StrokeThickness;
var style = new CanvasStrokeStyle
{
MiterLimit = geo.CanvasStrokeStyle.MiterLimit,
DashOffset = geo.CanvasStrokeStyle.DashOffset,
DashCap = geo.CanvasStrokeStyle.DashCap,
StartCap = geo.CanvasStrokeStyle.StartCap,
EndCap = geo.CanvasStrokeStyle.EndCap,
LineJoin = geo.CanvasStrokeStyle.LineJoin
};
if (geo.CanvasStrokeStyle.CustomDashStyle?.Length > 0)
{
actualDrawLength += style.DashOffset;
actualNoneLength += style.DashOffset;
var dashList = new List<float>();
var i = 0;
float sum = 0;
do
{
sum += geo.CanvasStrokeStyle.CustomDashStyle[i];
if (sum > actualDrawLength)
{
var needLength = geo.CanvasStrokeStyle.CustomDashStyle[i] -
(sum - actualDrawLength);
dashList.Add(needLength);
break;
}
dashList.Add(geo.CanvasStrokeStyle.CustomDashStyle[i]);
i = ++i % geo.CanvasStrokeStyle.CustomDashStyle.Length;
} while (true);
if (dashList.Count % 2 == 0)
dashList.Add(0);
dashList.Add(actualNoneLength);
style.CustomDashStyle = dashList.ToArray();
return style;
}
style.CustomDashStyle = new[] { actualDrawLength, actualNoneLength };
return style;
}
}
}
This diff is collapsed.
This diff is collapsed.
using System;
using System.Collections.Generic;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Geometry;
using SvgConverter.SvgParseForWin2D.Utilities;
namespace SvgConverter.SvgParseForWin2D
{
public class Win2DSvgGeometry : Win2DSvgNode
{
public CanvasGeometry CanvasGeometry
{
get
{
if (ClipGeometry != null)
return SourceCanvasGeometry.CombineWith(ClipGeometry, RenderTransform,
CanvasGeometryCombine.Intersect);
return SourceCanvasGeometry;
}
}
public CanvasGeometry SourceCanvasGeometry { get; set; }
public CanvasStrokeStyle CanvasStrokeStyle { get; set; }
public ICanvasBrush Stroke { get; set; }
public float StrokeThickness { get; set; }
public float PathLength { get; set; }
public double Progress { get; set; }
public bool IsDrewCompleted => Progress >= 1;
public ICanvasBrush Fill { get; set; }
public Vector2? RenderStroke(CanvasDrawingSession drawingSession, ICanvasBrush stroke)
{
if (drawingSession == null) return null;
if (IsDrewCompleted)
{
drawingSession.DrawGeometry(CanvasGeometry, stroke, StrokeThickness, CanvasStrokeStyle);
}
else
{
var drawLenght = (float) (PathLength * Progress);
Progress = drawLenght / PathLength;
var style = this.GetPartPathStyle(drawLenght);
drawingSession.DrawGeometry(CanvasGeometry, stroke,
StrokeThickness, style);
return Vector2.Transform(CanvasGeometry.ComputePointOnPath(drawLenght),
drawingSession.Transform);
}
return null;
}
public override void Dispose()
{
ClipGeometry?.Dispose();
SourceCanvasGeometry?.Dispose();
CanvasStrokeStyle?.Dispose();
GC.SuppressFinalize(this);
}
}
}
\ No newline at end of file
using System;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;
using Windows.UI;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
namespace SvgConverter.SvgParseForWin2D
{
public class Win2DSvgImage : Win2DSvgNode
{
public Win2DSvgImage(Rect viewRect, CanvasBitmap bitmap)
{
RenderMethod = RenderMethod.Composite;
ViewRect = viewRect;
SourceCanvasBitmap = bitmap;
}
public Rect ViewRect { get; set; }
public CanvasBitmap SourceCanvasBitmap { get; set; }
public void Draw(CanvasDrawingSession targetDrawSession)
{
if (SourceCanvasBitmap == null || ViewRect.Width == 0 || ViewRect.Height == 0)
{
return;
}
if (ClipGeometry != null)
{
using (var offScreen = new CanvasCommandList(SourceCanvasBitmap.Device))
{
using (var drawSession = offScreen.CreateDrawingSession())
{
drawSession.Clear(Colors.Transparent);
var imgCommandList = new CanvasCommandList(SourceCanvasBitmap.Device);
var markCommandList = new CanvasCommandList(SourceCanvasBitmap.Device);
using (var imgDrawSession = imgCommandList.CreateDrawingSession())
{
imgDrawSession.Clear(Colors.Transparent);
imgDrawSession.DrawImage(SourceCanvasBitmap, ViewRect);
}
using (var markDrawSession = markCommandList.CreateDrawingSession())
{
markDrawSession.Clear(Colors.Transparent);
markDrawSession.FillGeometry(ClipGeometry, Colors.Black);
}
var effect = new AlphaMaskEffect
{
Source = imgCommandList,
AlphaMask = markCommandList
};
drawSession.DrawImage(effect);
imgCommandList.Dispose();
markCommandList.Dispose();
}
targetDrawSession.Transform = RenderTransform;
targetDrawSession.DrawImage(offScreen);
}
}
else
{
targetDrawSession.Transform = RenderTransform;
targetDrawSession.DrawImage(SourceCanvasBitmap, ViewRect);
}
}
public static async Task<Win2DSvgImage> GetImage(ICanvasResourceCreator device, Rect viewRect,
byte[] imageBytes)
{
if (imageBytes == null) return null;
using (var randomAccessStream = new InMemoryRandomAccessStream())
{
var buffer = CryptographicBuffer.CreateFromByteArray(imageBytes);
await randomAccessStream.WriteAsync(buffer);
randomAccessStream.Seek(0);
var win2DSvgImg = new Win2DSvgImage(viewRect, await CanvasBitmap.LoadAsync(device, randomAccessStream));
return win2DSvgImg;
}
}
public override void Dispose()
{
ClipGeometry?.Dispose();
SourceCanvasBitmap?.Dispose();
GC.SuppressFinalize(this);
}
}
}
\ No newline at end of file
using System;
using System.Numerics;
using Microsoft.Graphics.Canvas.Geometry;
namespace SvgConverter.SvgParseForWin2D
{
public enum RenderMethod
{
Draw,
Fill,
Mark,
Composite,
MarkAndFill
}
public abstract class Win2DSvgNode : IDisposable
{
public string Id { get; set; }
public RenderMethod RenderMethod { get; set; }
public double RenderOpacity { get; set; } = 1;
public Matrix3x2 RenderTransform { get; set; } = Matrix3x2.Identity;
public CanvasGeometry ClipGeometry { get; set; }
public abstract void Dispose();
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Geometry;
namespace SvgConverter.TextParse
{
public class CharGeometry
{
public char Char { get; set; }
public string FontFamily { get; set; }
public float FontSize { get; set; }
public List<Vector2[]> PathList { get; set; }
public List<CanvasGeometry> GetGeometrys(ICanvasResourceCreator resourceCreator)
{
if (PathList == null || PathList.Count <= 0) return new List<CanvasGeometry>();
var list = new List<CanvasGeometry>();
foreach (var pathPoints in PathList)
{
if (pathPoints.Length < 2) continue;
var builder = new CanvasPathBuilder(resourceCreator);
builder.BeginFigure(pathPoints[0]);
for (var i = 1; i < pathPoints.Length; i++) builder.AddLine(pathPoints[i]);
builder.EndFigure(CanvasFigureLoop.Open);
list.Add(CanvasGeometry.CreatePath(builder));
builder.Dispose();
}
return list;
}
}
}
\ No newline at end of file
using System.Collections.Generic;
namespace SvgConverter.TextParse
{
public class PathMoveDirection
{
public static readonly PathMoveDirection Left = new PathMoveDirection
{
_id = -1,
OffsetPoint = new PathPoint(0, -1),
_nextMoveDirectionIds = new List<int>
{
4,
3,
5
}
};
public static readonly PathMoveDirection Right = new PathMoveDirection
{
_id = 0,
OffsetPoint = new PathPoint(0, 1),
_nextMoveDirectionIds = new List<int>
{
7,
2,
6
}
};
public static readonly PathMoveDirection Down = new PathMoveDirection
{
_id = 1,
OffsetPoint = new PathPoint(1, 0),
_nextMoveDirectionIds = new List<int>
{
3,
5,
6,
2
}
};
public static readonly PathMoveDirection LowerRight = new PathMoveDirection
{
_id = 2,
OffsetPoint = new PathPoint(1, 1),
_nextMoveDirectionIds = new List<int>
{
1,
6,
7,
0
}
};
public static readonly PathMoveDirection LowerLeft = new PathMoveDirection
{
_id = 3,
OffsetPoint = new PathPoint(1, -1),
_nextMoveDirectionIds = new List<int>
{
-1,
4,
5,
1
}
};
public static readonly PathMoveDirection LowerLeftLeft = new PathMoveDirection
{
_id = 4,
OffsetPoint = new PathPoint(1, -2),
_nextMoveDirectionIds = new List<int>
{
-1,
3,
5
}
};
public static readonly PathMoveDirection LowerLeftRight = new PathMoveDirection
{
_id = 5,
OffsetPoint = new PathPoint(2, -1),
_nextMoveDirectionIds = new List<int>
{
4,
3,
1,
6
}
};
public static readonly PathMoveDirection LowerRightLeft = new PathMoveDirection
{
_id = 6,
OffsetPoint = new PathPoint(2, 1),
_nextMoveDirectionIds = new List<int>
{
5,
1,
2,
7
}
};
public static readonly PathMoveDirection LowerRightRight = new PathMoveDirection
{
_id = 7,
OffsetPoint = new PathPoint(1, 2),
_nextMoveDirectionIds = new List<int>
{
6,
2,
0
}
};
private int _id;
private List<int> _nextMoveDirectionIds;
public PathPoint OffsetPoint { get; private set; }
public List<PathMoveDirection> GetNextMoveDirections()
{
var list = new List<PathMoveDirection>();
foreach (var id in _nextMoveDirectionIds)
if (id == Down._id)
list.Add(Down);
else if (id == Right._id)
list.Add(Right);
else if (id == LowerRight._id)
list.Add(LowerRight);
else if (id == LowerLeft._id)
list.Add(LowerLeft);
else if (id == Left._id)
list.Add(Left);
else if (id == LowerRightLeft._id)
list.Add(LowerRightLeft);
else if (id == LowerRightRight._id)
list.Add(LowerRightRight);
else if (id == LowerLeftLeft._id)
list.Add(LowerLeftLeft);
else if (id == LowerLeftRight._id) list.Add(LowerLeftRight);
return list;
}
}
}
\ No newline at end of file
using System.Numerics;
namespace SvgConverter.TextParse
{
public struct PathPoint
{
public PathPoint(int row, int col)
{
Row = row;
Col = col;
}
public int Row { get; }
public int Col { get; }
public Vector2 ToVector2(Vector2 refSplitVector2)
{
return new Vector2
{
X = refSplitVector2.X * (Col + 0.5f),
Y = refSplitVector2.Y * (Row + 0.5f)
};
}
public override bool Equals(object obj)
{
if (!(obj is PathPoint)) return false;
var point = (PathPoint) obj;
return Row == point.Row &&
Col == point.Col;
}
public override int GetHashCode()
{
var hashCode = 1084646500;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + Row.GetHashCode();
hashCode = hashCode * -1521134295 + Col.GetHashCode();
return hashCode;
}
public static PathPoint operator +(PathPoint point1, PathPoint point2)
{
return new PathPoint(point1.Row + point2.Row, point1.Col + point2.Col);
}
public static bool operator ==(PathPoint point1, PathPoint point2)
{
return point1.Row == point2.Row && point1.Col == point2.Col;
}
public static bool operator !=(PathPoint point1, PathPoint point2)
{
return point1.Row != point2.Row || point1.Col != point2.Col;
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Windows.Foundation;
using Windows.UI.Text;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Geometry;
using Microsoft.Graphics.Canvas.Text;
namespace SvgConverter.TextParse
{
public static class TextParseHelper
{
public static CharGeometry GetGeometrys(int rowCount, int colCount, int pathWidthLimit, char text,
string fontFamily, float fontSize)
{
var textLayout = new CanvasTextLayout(CanvasDevice.GetSharedDevice(), new string(new[] {text}),
new CanvasTextFormat
{
FontWeight = new FontWeight
{
Weight = 1
},
FontFamily = fontFamily,
FontSize = fontSize,
WordWrapping = CanvasWordWrapping.NoWrap
}, 0, 0);
var textDotArray = GetDotArray(textLayout, rowCount, colCount);
var drawBounds = textLayout.DrawBounds;
textLayout.Dispose();
var directs = new List<PathMoveDirection>
{
PathMoveDirection.Right,
PathMoveDirection.LowerRightRight,
PathMoveDirection.LowerRight,
PathMoveDirection.LowerRightLeft,
PathMoveDirection.Down,
PathMoveDirection.LowerLeftLeft,
PathMoveDirection.LowerLeft,
PathMoveDirection.LowerLeftRight
};
var pathList = new List<List<PathPoint>>();
for (var i = 0; i < rowCount; i++)
for (var j = 0; j < colCount; j++)
{
if (!textDotArray[i, j]) continue;
var list = GetMaxPath(textDotArray, new PathPoint(i, j), directs);
textDotArray[i, j] = false;
if (list == null) continue;
list.Insert(0, new PathPoint(i, j));
pathList.Add(list);
foreach (var p in list)
for (var k = -pathWidthLimit / 2; k < pathWidthLimit / 2 + 1; k++)
for (var l = -pathWidthLimit / 2; l < pathWidthLimit / 2 + 1; l++)
InvalidPoint(textDotArray, p, new PathPoint(k, l));
}
return new CharGeometry
{
Char = text,
FontFamily = fontFamily,
FontSize = fontSize,
PathList = GetGeometrys(pathList, new Size(drawBounds.Width, drawBounds.Height),
rowCount, colCount)
};
}
private static List<Vector2[]> GetGeometrys(List<List<PathPoint>> pathList, Size sise, int rowCount,
int colCount)
{
if (pathList == null || pathList.Count <= 0) return new List<Vector2[]>();
var splitPoint = new Point(sise.Width / colCount, sise.Height / rowCount).ToVector2();
return (from pathPoints in pathList
where pathPoints.Count >= 2
select (from point in pathPoints select point.ToVector2(splitPoint))
into points
select points.ToArray()).ToList();
}
private static void InvalidPoint(bool[,] dotArrays, PathPoint sourcePoint, PathPoint offsetPoint)
{
var point = sourcePoint + offsetPoint;
var i = dotArrays.GetLength(0);
var j = dotArrays.GetLength(1);
if (0 <= point.Row && point.Row < i && 0 <= point.Col && point.Col < j)
dotArrays[point.Row, point.Col] = false;
}
private static List<PathPoint> GetMaxPath(bool[,] dotArrays, PathPoint startPoint,
IEnumerable<PathMoveDirection> canMoveDirections)
{
var maxLengthList = new List<PathPoint>();
foreach (var direct in canMoveDirections)
{
if (!CanMove(dotArrays, startPoint, direct))
continue;
var dList = GetPath(dotArrays, startPoint, direct);
if (dList != null && dList.Count > maxLengthList.Count) maxLengthList = dList;
}
return maxLengthList;
}
private static List<PathPoint> GetPath(bool[,] dotArrays, PathPoint startPoint,
PathMoveDirection moveDirection)
{
var list = new List<PathPoint>();
if (!CanMove(dotArrays, startPoint, moveDirection))
return GetMaxPath(dotArrays, startPoint, moveDirection.GetNextMoveDirections());
var point = startPoint + moveDirection.OffsetPoint;
list.Add(point);
var next = GetPath(dotArrays, point, moveDirection);
if (next != null)
list.AddRange(next);
return list;
}
private static bool CanMove(bool[,] dotArrays, PathPoint startPoint, PathMoveDirection moveDirection)
{
var nextPoint = startPoint + moveDirection.OffsetPoint;
var next2Point = nextPoint + moveDirection.OffsetPoint;
if (0 <= nextPoint.Row
&& nextPoint.Row < dotArrays.GetLength(0)
&& 0 <= nextPoint.Col
&& nextPoint.Col < dotArrays.GetLength(1)
&& 0 <= next2Point.Row
&& next2Point.Row < dotArrays.GetLength(0)
&& 0 <= next2Point.Col
&& next2Point.Col < dotArrays.GetLength(1))
return dotArrays[nextPoint.Row, nextPoint.Col] &&
dotArrays[next2Point.Row, next2Point.Col];
return false;
}
private static bool[,] GetDotArray(CanvasTextLayout text, int rowCount, int colCount)
{
var path = new bool[rowCount, colCount];
var startVector2 = new Vector2((float) text.DrawBounds.X, (float) text.DrawBounds.Y);
var rectSize = new Size(text.DrawBounds.Width / colCount, text.DrawBounds.Height / rowCount);
var textGeometry = CanvasGeometry.CreateText(text);
for (var i = 0; i < rowCount; i++)
{
startVector2.X = (float) text.DrawBounds.X;
for (var j = 0; j < colCount; j++)
{
path[i, j] = textGeometry.FillContainsPoint(
new Point(startVector2.X + rectSize.Height / 2, startVector2.Y + rectSize.Width / 2)
.ToVector2());
startVector2.X += (float) rectSize.Width;
}
startVector2.Y += (float) rectSize.Height;
}
textGeometry.Dispose();
return path;
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text;
namespace SvgConverter.TextParse
{
public class TextSvgElement : AnimationBase
{
private readonly Dictionary<int, Tuple<float, CharGeometry>> _charGeometrys =
new Dictionary<int, Tuple<float, CharGeometry>>();
private readonly List<Tuple<Rect, Win2DCharSvgElement>> _charSvgElements =
new List<Tuple<Rect, Win2DCharSvgElement>>();
private readonly object _lockobj = new object();
private float _progress;
private TextSvgElement()
{
}
public double TotalLength { get; private set; }
public double DrewLength => TotalLength * _progress;
public override float Progress
{
get => _progress;
set
{
_progress = value >= 1 ? 1 : value;
RefreshDrawProgress();
}
}
public string Text { get; private set; }
public string FontFamily { get; private set; }
public Color Foreground { get; private set; }
public double FontSize { get; private set; }
/// <summary>
/// 刷新绘制进度
/// </summary>
private void RefreshDrawProgress()
{
lock (_lockobj)
{
var length = DrewLength;
foreach (var item in _charSvgElements)
if (length >= item.Item2.TotalLength)
{
length -= item.Item2.TotalLength;
item.Item2.Progress = 1;
}
else
{
item.Item2.Progress = (float) (length / item.Item2.TotalLength);
length = 0;
}
}
}
public override Vector2? Draw(
CanvasDrawingSession drawingSession, float drawProgress)
{
lock (_lockobj)
{
Progress += drawProgress;
var sourceTransform = drawingSession.Transform;
drawingSession.Transform = Matrix3x2.Identity;
var needDrawLenght = TotalLength * drawProgress;
var charCommandList = new CanvasCommandList(drawingSession);
var charDrawingSession = charCommandList.CreateDrawingSession();
try
{
foreach (var item in _charSvgElements)
{
charDrawingSession.Transform =
Matrix3x2.CreateTranslation(new Point(item.Item1.X, item.Item1.Y)
.ToVector2());
charDrawingSession.Transform = charDrawingSession.Transform * sourceTransform;
if (item.Item2.Progress >= 1)
{
item.Item2.Draw(charDrawingSession, 0);
}
else
{
var leftLength = item.Item2.TotalLength - item.Item2.DrewLength;
if (needDrawLenght > leftLength)
{
item.Item2.Draw(charDrawingSession, 1 - item.Item2.Progress);
needDrawLenght -= leftLength;
}
else
{
var p = item.Item2.Draw(charDrawingSession,
(float) (needDrawLenght / item.Item2.TotalLength));
if (p.HasValue) return Vector2.Transform(p.Value, drawingSession.Transform);
}
}
}
return null;
}
finally
{
charDrawingSession.Dispose();
drawingSession.DrawImage(charCommandList);
charCommandList.Dispose();
}
}
}
public override void Dispose()
{
lock (_lockobj)
{
foreach (var node in _charSvgElements) node.Item2.Dispose();
}
GC.SuppressFinalize(this);
}
public void ChangeFontColor(Color newFontColor)
{
if (Foreground != newFontColor)
lock (_lockobj)
{
Foreground = newFontColor;
foreach (var item in _charSvgElements) item.Item2.ChangeFontColor(newFontColor);
}
}
public static async Task<TextSvgElement> Parse(ICanvasResourceCreator resourceCreator, string text,
string fontFamily, Color foreground,
float fontSize = 72f)
{
if (string.IsNullOrWhiteSpace(text))
return null;
var chars = text.ToCharArray();
var strLayout = new CanvasTextLayout(CanvasDevice.GetSharedDevice(), text,
new CanvasTextFormat
{
FontFamily = fontFamily,
FontSize = fontSize,
WordWrapping = CanvasWordWrapping.NoWrap
}, 0, 0);
var textGeo = new TextSvgElement
{
Text = text,
FontFamily = fontFamily,
Foreground = foreground,
FontSize = fontSize,
ViewBox = strLayout.LayoutBounds
};
var taskDic = new Dictionary<char, Task>();
var lockobj = new object();
for (var i = 0; i < chars.Length; i++)
{
if (taskDic.Keys.Contains(chars[i]) || chars[i].Equals(' ')) continue;
var tuple = new Tuple<Dictionary<int, Tuple<float, CharGeometry>>, int, char, string>(
textGeo._charGeometrys, i,
chars[i], fontFamily);
var task =
new Task(o =>
{
if (!(o is Tuple<Dictionary<int, Tuple<float, CharGeometry>>, int, char, string> t))
return;
var charGeometrys = t.Item1;
var index = t.Item2;
var letter = t.Item3;
var font = t.Item4;
int rowCount = 72, colCount = 72, pathWidthLimit = 6;
var thickness = fontSize / 10f;
if (char.IsNumber(letter))
{
rowCount = 48;
colCount = 16;
pathWidthLimit = 8;
thickness *= 2f;
}
else if (char.IsUpper(letter))
{
rowCount = 48;
colCount = 16;
pathWidthLimit = 8;
thickness *= 2f;
}
else if (char.IsLower(letter))
{
rowCount = 48;
colCount = 16;
pathWidthLimit = 8;
thickness *= 1.5f;
}
else if (char.IsPunctuation(letter) || char.IsSymbol(letter))
{
rowCount = 16;
colCount = 16;
pathWidthLimit = 4;
}
var charGeo = TextParseHelper.GetGeometrys(rowCount, colCount, pathWidthLimit, letter, font,
fontSize);
lock (lockobj)
{
charGeometrys[index] = new Tuple<float, CharGeometry>(thickness, charGeo);
}
}, tuple);
taskDic[chars[i]] = task;
task.Start();
}
await Task.WhenAll(taskDic.Values.ToArray());
for (var i = 0; i < chars.Length; i++)
{
if (chars[i].Equals(' ')) continue;
var rect = strLayout.GetCharacterRegions(i, 1)[0].LayoutBounds;
if (textGeo._charGeometrys.TryGetValue(text.IndexOf(chars[i]), out var charGeo))
{
var charSvg =
Win2DCharSvgElement.Parse(resourceCreator, charGeo.Item2, foreground, charGeo.Item1);
textGeo._charSvgElements.Add(new Tuple<Rect, Win2DCharSvgElement>(rect, charSvg));
textGeo.TotalLength += charSvg.TotalLength;
}
}
strLayout.Dispose();
return textGeo;
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Windows.Foundation;
using Windows.UI;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Geometry;
using Microsoft.Graphics.Canvas.Text;
using SvgConverter.SvgParseForWin2D;
namespace SvgConverter.TextParse
{
public class Win2DCharSvgElement : Win2DSvgElement
{
internal Win2DCharSvgElement()
{
}
public char Char { get; private set; }
public string FontFamily { get; private set; }
public Color Foreground { get; private set; }
public double FontSize { get; private set; }
public void ChangeFontColor(Color newFontColor)
{
if (Foreground != newFontColor && Device != null)
{
Foreground = newFontColor;
if (SvgNodeList?.Count > 0 &&
SvgNodeList[0] is Win2DSvgGeometry geo)
{
geo.Fill = new CanvasSolidColorBrush(Device, newFontColor);
geo.Stroke = new CanvasSolidColorBrush(Device, newFontColor);
}
}
}
public static Win2DCharSvgElement Parse(ICanvasResourceCreator resourceCreator, CharGeometry charGeo,
Color foreground, float thickness)
{
var textLayout = new CanvasTextLayout(resourceCreator, new string(new[] {charGeo.Char}),
new CanvasTextFormat
{
FontFamily = charGeo.FontFamily,
FontSize = charGeo.FontSize,
WordWrapping = CanvasWordWrapping.NoWrap
}, 0, 0);
var win2DSvg = new Win2DCharSvgElement
{
Device = resourceCreator.Device,
Char = charGeo.Char,
Foreground = foreground,
FontFamily = charGeo.FontFamily,
FontSize = charGeo.FontSize,
ViewBox =
new Rect(new Point(), new Size(textLayout.LayoutBounds.Width, textLayout.LayoutBounds.Height)),
SvgNodeList = new List<Win2DSvgNode>()
};
var drawList = charGeo.GetGeometrys(resourceCreator).Select(path => new Win2DSvgGeometry
{
SourceCanvasGeometry = path,
PathLength = path.ComputePathLength(),
RenderOpacity = 1,
Stroke = new CanvasSolidColorBrush(resourceCreator, Colors.Black),
Fill = new CanvasSolidColorBrush(resourceCreator, Colors.Transparent),
StrokeThickness = thickness,
RenderMethod = RenderMethod.Mark,
CanvasStrokeStyle = new CanvasStrokeStyle
{
LineJoin = CanvasLineJoin.Round,
StartCap = CanvasCapStyle.Round,
EndCap = CanvasCapStyle.Round
},
RenderTransform =
Matrix3x2.CreateTranslation(new Point(textLayout.DrawBounds.X, textLayout.DrawBounds.Y)
.ToVector2())
}).ToList();
var win2DGeo = new Win2DSvgGeometry
{
SourceCanvasGeometry = CanvasGeometry.CreateText(textLayout),
CanvasStrokeStyle = new CanvasStrokeStyle(),
RenderOpacity = 1,
Stroke = new CanvasSolidColorBrush(resourceCreator, foreground),
Fill = new CanvasSolidColorBrush(resourceCreator, foreground),
StrokeThickness = 1,
RenderMethod = RenderMethod.Composite
};
win2DSvg.TotalLength = drawList
.Aggregate<Win2DSvgGeometry, double>(0,
(current, item) => current + item.PathLength);
win2DSvg.SvgNodeList.Add(win2DGeo);
win2DSvg.SvgNodeList.AddRange(drawList);
win2DSvg.DrawNodeList = drawList;
return win2DSvg;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment