diff --git a/Output/SharpVectors.Converters.Wpf.dll b/Output/SharpVectors.Converters.Wpf.dll
index 9a2cb404d..5b7c007f7 100644
Binary files a/Output/SharpVectors.Converters.Wpf.dll and b/Output/SharpVectors.Converters.Wpf.dll differ
diff --git a/Output/SharpVectors.Core.dll b/Output/SharpVectors.Core.dll
index 8d86cc415..7c9ea3dcc 100644
Binary files a/Output/SharpVectors.Core.dll and b/Output/SharpVectors.Core.dll differ
diff --git a/Output/SharpVectors.Css.dll b/Output/SharpVectors.Css.dll
index 7bc440a49..69a1d6471 100644
Binary files a/Output/SharpVectors.Css.dll and b/Output/SharpVectors.Css.dll differ
diff --git a/Output/SharpVectors.Dom.dll b/Output/SharpVectors.Dom.dll
index 20e962e24..2a3855b26 100644
Binary files a/Output/SharpVectors.Dom.dll and b/Output/SharpVectors.Dom.dll differ
diff --git a/Output/SharpVectors.Model.dll b/Output/SharpVectors.Model.dll
index ec1e87960..1d32dfeea 100644
Binary files a/Output/SharpVectors.Model.dll and b/Output/SharpVectors.Model.dll differ
diff --git a/Output/SharpVectors.Rendering.Gdi.dll b/Output/SharpVectors.Rendering.Gdi.dll
index 6d21fa771..925fe6bc0 100644
Binary files a/Output/SharpVectors.Rendering.Gdi.dll and b/Output/SharpVectors.Rendering.Gdi.dll differ
diff --git a/Output/SharpVectors.Rendering.Wpf.dll b/Output/SharpVectors.Rendering.Wpf.dll
index bfa08b916..796491a4d 100644
Binary files a/Output/SharpVectors.Rendering.Wpf.dll and b/Output/SharpVectors.Rendering.Wpf.dll differ
diff --git a/Output/SharpVectors.Runtime.Wpf.dll b/Output/SharpVectors.Runtime.Wpf.dll
index 39bb972d3..b79e11fcc 100644
Binary files a/Output/SharpVectors.Runtime.Wpf.dll and b/Output/SharpVectors.Runtime.Wpf.dll differ
diff --git a/Samples/WpfSvgTestBox/DebugPage.xaml b/Samples/WpfSvgTestBox/DebugPage.xaml
index e80d9de1a..f55a5b267 100644
--- a/Samples/WpfSvgTestBox/DebugPage.xaml
+++ b/Samples/WpfSvgTestBox/DebugPage.xaml
@@ -3,12 +3,17 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
xmlns:local="clr-namespace:WpfSvgTestBox"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Title="DebugPage">
-
+
+
+
diff --git a/Samples/WpfSvgTestBox/DebugPage.xaml.cs b/Samples/WpfSvgTestBox/DebugPage.xaml.cs
index f2a5499c4..ae88dc90f 100644
--- a/Samples/WpfSvgTestBox/DebugPage.xaml.cs
+++ b/Samples/WpfSvgTestBox/DebugPage.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics;
using System.Windows.Controls;
@@ -7,28 +8,77 @@ namespace WpfSvgTestBox
///
/// Interaction logic for DebugPage.xaml
///
- public partial class DebugPage : Page
+ public partial class DebugPage : Page, ITraceTextSink
{
+ private delegate void AppendTextDelegate(string msg, string style);
+
+ private TraceListener _listener;
+
public DebugPage()
{
InitializeComponent();
+
+ textEditor.IsReadOnly = true;
+
+ Trace.UseGlobalLock = true;
+
+ _listener = new TraceTextSource(this);
+ Trace.Listeners.Add(_listener);
}
public void Startup()
{
- if (traceDocument != null)
+ if (_listener == null)
{
- traceDocument.Startup();
+ _listener = new TraceTextSource(this);
+ Trace.Listeners.Add(_listener);
}
+
+ Trace.WriteLine("Startup");
}
public void Shutdown()
{
- if (traceDocument != null)
+ Trace.WriteLine("Shutdown");
+ if (_listener != null)
{
- traceDocument.Shutdown();
+ Trace.Listeners.Remove(_listener);
+ _listener.Dispose();
+ _listener = null;
}
}
+ public void Event(string msg, TraceEventType eventType)
+ {
+ Append(msg, eventType.ToString());
+ }
+
+ public void Fail(string msg)
+ {
+ Append(msg, "Fail");
+ }
+
+ private void Append(string msg, string style)
+ {
+ if (Dispatcher.CheckAccess())
+ {
+ if (!this.IsLoaded)
+ {
+ return;
+ }
+ if (string.IsNullOrWhiteSpace(style))
+ {
+ textEditor.AppendText(msg + Environment.NewLine);
+ }
+ else
+ {
+ textEditor.AppendText(style + ": " + msg + Environment.NewLine);
+ }
+ }
+ else
+ {
+ Dispatcher.Invoke(new AppendTextDelegate(Append), msg, style);
+ }
+ }
}
}
diff --git a/Samples/WpfTestThreadSafety/App.config b/Samples/WpfTestThreadSafety/App.config
new file mode 100644
index 000000000..88fa4027b
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/WpfTestThreadSafety/App.ico b/Samples/WpfTestThreadSafety/App.ico
new file mode 100644
index 000000000..bf398870c
Binary files /dev/null and b/Samples/WpfTestThreadSafety/App.ico differ
diff --git a/Samples/WpfTestThreadSafety/App.xaml b/Samples/WpfTestThreadSafety/App.xaml
new file mode 100644
index 000000000..5bbf37dba
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/Samples/WpfTestThreadSafety/App.xaml.cs b/Samples/WpfTestThreadSafety/App.xaml.cs
new file mode 100644
index 000000000..f66a2fe7b
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace WpfTestThreadSafety
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/Samples/WpfTestThreadSafety/MainWindow.xaml b/Samples/WpfTestThreadSafety/MainWindow.xaml
new file mode 100644
index 000000000..b0c5bdd7d
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/MainWindow.xaml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+ Verbose
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/WpfTestThreadSafety/MainWindow.xaml.cs b/Samples/WpfTestThreadSafety/MainWindow.xaml.cs
new file mode 100644
index 000000000..bb27386fa
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/MainWindow.xaml.cs
@@ -0,0 +1,346 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using System.Runtime.InteropServices;
+
+using System.Windows;
+using System.Windows.Media;
+
+using SharpVectors.Converters;
+using SharpVectors.Renderers.Wpf;
+
+namespace WpfTestThreadSafety
+{
+ public sealed class ImageData
+ {
+ private string _fileName;
+ private Drawing _drawing;
+
+ public ImageData()
+ {
+ }
+
+ public ImageData(Drawing drawing, string fileName)
+ {
+ _drawing = drawing;
+ _fileName = fileName;
+ }
+
+ public string Name
+ {
+ get {
+ return _fileName;
+ }
+ }
+
+ public ImageSource Image
+ {
+ get {
+ return new DrawingImage(_drawing);
+ }
+ }
+ }
+
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ private delegate void AppendImageDelegate(Drawing drawing, string fileName);
+ private delegate void AppendTextDelegate(string msg, string style);
+
+ private const string W3CDirPrefix = "Svg";
+ private const string LocalDirBase = @"..\..\..\W3cSvgTestSuites\";
+
+ [DllImport("Shlwapi.dll", EntryPoint = "PathIsDirectoryEmpty")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsDirectoryEmpty([MarshalAs(UnmanagedType.LPStr)]string directory);
+
+ private const int NumberOfImages = 300;
+ private const int NumberOfColumns = 100;
+ private const int NumberOfConsumers = 8;
+
+ private bool _isVerbose;
+ private int _columnCount;
+ private int _imageCount;
+
+ private ObservableCollection _imageList;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+
+ _imageList = new ObservableCollection();
+ this.DataContext = this;
+ }
+
+ public ObservableCollection ImageList
+ {
+ get {
+ return _imageList;
+ }
+ }
+
+ private void OnWindowLoaded(object sender, RoutedEventArgs e)
+ {
+ this.SetValidSvgDir();
+
+ }
+
+ private void OnWindowClosed(object sender, EventArgs e)
+ {
+
+ }
+
+ private void OnWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+
+ }
+
+ private void SetValidSvgDir()
+ {
+ string svgDir;
+ if (GetValidSvgTestsDir(out svgDir, 1, 1))
+ {
+ txtSvgSource.Text = svgDir;
+ return;
+ }
+ if (GetValidSvgTestsDir(out svgDir, 1, 2))
+ {
+ txtSvgSource.Text = svgDir;
+ return;
+ }
+ if (GetValidSvgTestsDir(out svgDir, 1, 0)) // this has fewer that 300 images
+ {
+ txtSvgSource.Text = svgDir;
+ return;
+ }
+ }
+
+ private void UpdateDrawing(string svgFilePath)
+ {
+ var wpfSettings = new WpfDrawingSettings();
+ wpfSettings.CultureInfo = wpfSettings.NeutralCultureInfo;
+ using (var textReader = new StreamReader(svgFilePath))
+ {
+ using (var fileReader = new FileSvgReader(wpfSettings))
+ {
+ _imageCount++;
+ try
+ {
+ if (_isVerbose)
+ {
+ this.AppendLine("Start Converting: " + svgFilePath);
+ }
+ else
+ {
+ _columnCount++;
+ AppendText("*");
+ if (_columnCount >= NumberOfColumns)
+ {
+ _columnCount = 0;
+ if (_imageCount < NumberOfImages)
+ {
+ AppendLine("");
+ }
+ }
+ }
+
+ fileReader.SaveXaml = false;
+ fileReader.SaveZaml = false;
+ var drawing = fileReader.Read(textReader);
+ drawing.Freeze();
+
+ AppendImage(drawing, Path.GetFileNameWithoutExtension(svgFilePath));
+
+ if (_isVerbose)
+ {
+ this.AppendLine("Completed Converting: " + svgFilePath);
+ }
+ }
+ catch (Exception ex)
+ {
+ if (_isVerbose)
+ {
+ AppendClear();
+ }
+ this.AppendLine("File: " + svgFilePath);
+ AppendError(ex.ToString());
+ }
+ }
+ }
+ }
+
+ public void AppendError(string msg)
+ {
+ AppendLine(msg, "Error");
+ }
+
+ public void AppendClear()
+ {
+ AppendLine(string.Empty, "Clear");
+ }
+
+ private void AppendImage(Drawing drawing, string fileName)
+ {
+ if (Dispatcher.CheckAccess())
+ {
+ _imageList.Add(new ImageData(drawing, fileName));
+ }
+ else
+ {
+ Dispatcher.Invoke(new AppendImageDelegate(AppendImage), drawing, fileName);
+ }
+ }
+
+ private void AppendText(string msg, string style = "")
+ {
+ if (Dispatcher.CheckAccess())
+ {
+ txtDebug.AppendText(msg);
+ }
+ else
+ {
+ Dispatcher.Invoke(new AppendTextDelegate(AppendText), msg, string.Empty);
+ }
+ }
+
+ private void AppendLine(string msg, string style = null)
+ {
+ if (Dispatcher.CheckAccess())
+ {
+ if (string.IsNullOrWhiteSpace(style))
+ {
+ txtDebug.AppendText(msg + Environment.NewLine);
+ }
+ else
+ {
+ if (style.Equals("Clear", StringComparison.OrdinalIgnoreCase))
+ {
+ txtDebug.Clear();
+ return;
+ }
+ else
+ {
+ txtDebug.AppendText(style + ": " + msg + Environment.NewLine);
+ }
+ }
+
+ txtDebug.CaretIndex = txtDebug.Text.Length;
+ txtDebug.ScrollToEnd();
+ }
+ else
+ {
+ Dispatcher.Invoke(new AppendTextDelegate(AppendLine), msg, style);
+ }
+ }
+
+ private static bool GetValidSvgTestsDir(out string svgDir, int majorVersion, int minorVersion)
+ {
+ svgDir = "";
+
+ string versionSuffix = string.Format("{0}{1}", majorVersion, minorVersion);
+ var suiteDirName = W3CDirPrefix + versionSuffix;
+ var localSuitePath = Path.GetFullPath(Path.Combine(LocalDirBase, suiteDirName));
+ if (Directory.Exists(localSuitePath) == false)
+ {
+ return false;
+ }
+ if (IsTestSuiteAvailable(localSuitePath))
+ {
+ svgDir = Path.Combine(localSuitePath, "svg");
+ return true;
+ }
+ return false;
+ }
+
+ private static bool IsTestSuiteAvailable(string testPath)
+ {
+ if (string.IsNullOrWhiteSpace(testPath) || Directory.Exists(testPath) == false)
+ {
+ return false;
+ }
+ string svgDir = Path.Combine(testPath, "svg");
+ if (!Directory.Exists(svgDir) || IsDirectoryEmpty(svgDir) == true)
+ {
+ return false;
+ }
+ string pngDir = Path.Combine(testPath, "png");
+ if (!Directory.Exists(pngDir) || IsDirectoryEmpty(pngDir) == true)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private async void OnStartClick(object sender, RoutedEventArgs e)
+ {
+ string svgPath = txtSvgSource.Text;
+ if (string.IsNullOrWhiteSpace(svgPath) || Directory.Exists(svgPath) == false)
+ {
+ return;
+ }
+
+ txtDebug.Clear();
+ _imageList.Clear();
+
+ _columnCount = 0;
+ _imageCount = 0;
+ _isVerbose = (chkVerbose.IsChecked != null && chkVerbose.IsChecked.Value);
+
+ btnStart.IsEnabled = false;
+ chkVerbose.IsEnabled = false;
+
+ var queue = new ConcurrentQueue();
+
+ int imageCount = 0;
+ foreach (var svgFilePath in Directory.EnumerateFiles(svgPath, "*.svg"))
+ {
+ // Eliminate any compressed file, not supported in this test...
+ if (svgFilePath.EndsWith(".svgz", StringComparison.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ queue.Enqueue(svgFilePath);
+
+ imageCount++;
+ if (imageCount >= NumberOfImages)
+ {
+ break;
+ }
+ }
+
+ AppendLine("Starting Tests ****");
+ if (_isVerbose)
+ {
+ AppendLine("");
+ }
+
+ var allTasks = new List();
+
+ for (int i = 0; i < NumberOfConsumers; ++i)
+ {
+ allTasks.Add(Task.Run(() =>
+ {
+ while (queue.TryDequeue(out string imageData))
+ {
+ UpdateDrawing(imageData);
+ }
+ }));
+ }
+
+ await Task.WhenAll(allTasks);
+
+ AppendLine("");
+ AppendLine("**** Completed Tests");
+
+ btnStart.IsEnabled = true;
+ chkVerbose.IsEnabled = true;
+ }
+ }
+}
diff --git a/Samples/WpfTestThreadSafety/Properties/AssemblyInfo.cs b/Samples/WpfTestThreadSafety/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..777c56402
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WpfTestThreadSafety")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("WpfTestThreadSafety")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Samples/WpfTestThreadSafety/Properties/Resources.Designer.cs b/Samples/WpfTestThreadSafety/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..cacdf9897
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/Properties/Resources.Designer.cs
@@ -0,0 +1,68 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace WpfTestThreadSafety.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WpfTestThreadSafety.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Samples/WpfTestThreadSafety/Properties/Resources.resx b/Samples/WpfTestThreadSafety/Properties/Resources.resx
new file mode 100644
index 000000000..af7dbebba
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Samples/WpfTestThreadSafety/Properties/Settings.Designer.cs b/Samples/WpfTestThreadSafety/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..6d0f8adad
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/Properties/Settings.Designer.cs
@@ -0,0 +1,29 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace WpfTestThreadSafety.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Samples/WpfTestThreadSafety/Properties/Settings.settings b/Samples/WpfTestThreadSafety/Properties/Settings.settings
new file mode 100644
index 000000000..033d7a5e9
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/WpfTestThreadSafety/WpfTestThreadSafety.csproj b/Samples/WpfTestThreadSafety/WpfTestThreadSafety.csproj
new file mode 100644
index 000000000..7a549b09e
--- /dev/null
+++ b/Samples/WpfTestThreadSafety/WpfTestThreadSafety.csproj
@@ -0,0 +1,134 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {19ED33D1-7D07-43ED-878A-16630CD4035D}
+ WinExe
+ WpfTestThreadSafety
+ WpfTestThreadSafety
+ v4.5.2
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ App.ico
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+ {e8056611-e49c-4bc3-a682-a629d5cec11c}
+ SharpVectors.Converters.Wpf
+
+
+ {d6bb65fc-240e-4241-b2ed-a7fb3f13e978}
+ SharpVectors.Core
+
+
+ {351b0a6e-2f6b-497a-844b-dcb5a502fb0d}
+ SharpVectors.Css
+
+
+ {fe34cbc0-d23c-4a95-ba64-83a031814010}
+ SharpVectors.Dom
+
+
+ {5d336f48-3fb9-4382-b4b9-06974c764007}
+ SharpVectors.Model
+
+
+ {a2576ce0-e492-490f-97e9-c0e7abafaf27}
+ SharpVectors.Rendering.Wpf
+
+
+ {2cd52982-a1c2-4a14-9d69-d64719357216}
+ SharpVectors.Runtime.Wpf
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/WpfW3cSvgTestSuite/OptionSettings.cs b/Samples/WpfW3cSvgTestSuite/OptionSettings.cs
index 4590c0326..ee5cfb111 100644
--- a/Samples/WpfW3cSvgTestSuite/OptionSettings.cs
+++ b/Samples/WpfW3cSvgTestSuite/OptionSettings.cs
@@ -30,6 +30,10 @@ private static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder,
private static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name,
IntPtr bindingContext, [Out] out IntPtr pidl, uint sfgaoIn, [Out] out uint psfgaoOut);
+ [DllImport("Shlwapi.dll", EntryPoint = "PathIsDirectoryEmpty")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsDirectoryEmpty([MarshalAs(UnmanagedType.LPStr)]string directory);
+
#endregion
#region Public Events
@@ -43,10 +47,6 @@ private static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)]
private const string ParentSymbol = "..\\";
private const string SharpVectors = "SharpVectors";
- [DllImport("Shlwapi.dll", EntryPoint = "PathIsDirectoryEmpty")]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool IsDirectoryEmpty([MarshalAs(UnmanagedType.LPStr)]string directory);
-
private bool _hidePathsRoot;
private string _webSuitePath;
private string _localSuitePath;
diff --git a/Samples/WpfW3cSvgTestSuite/Output/SvgTestResults12.xml b/Samples/WpfW3cSvgTestSuite/Output/SvgTestResults12.xml
index 28034cadd..a1adb5a3e 100644
--- a/Samples/WpfW3cSvgTestSuite/Output/SvgTestResults12.xml
+++ b/Samples/WpfW3cSvgTestSuite/Output/SvgTestResults12.xml
@@ -19,4 +19,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SharpVectorsAll.sln b/SharpVectorsAll.sln
index 75706db8c..3e73c2ae9 100644
--- a/SharpVectorsAll.sln
+++ b/SharpVectorsAll.sln
@@ -40,6 +40,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GdiSvgTestBox", "Samples\Gd
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfTestSvgControl", "Samples\WpfTestSvgControl\WpfTestSvgControl.csproj", "{28586359-004C-45B5-823E-38F714784B31}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfTestThreadSafety", "Samples\WpfTestThreadSafety\WpfTestThreadSafety.csproj", "{19ED33D1-7D07-43ED-878A-16630CD4035D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -149,6 +151,12 @@ Global
{28586359-004C-45B5-823E-38F714784B31}.Documentation|Any CPU.Build.0 = Debug|Any CPU
{28586359-004C-45B5-823E-38F714784B31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28586359-004C-45B5-823E-38F714784B31}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19ED33D1-7D07-43ED-878A-16630CD4035D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {19ED33D1-7D07-43ED-878A-16630CD4035D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19ED33D1-7D07-43ED-878A-16630CD4035D}.Documentation|Any CPU.ActiveCfg = Debug|Any CPU
+ {19ED33D1-7D07-43ED-878A-16630CD4035D}.Documentation|Any CPU.Build.0 = Debug|Any CPU
+ {19ED33D1-7D07-43ED-878A-16630CD4035D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {19ED33D1-7D07-43ED-878A-16630CD4035D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -163,6 +171,7 @@ Global
{406733B7-B9C5-4100-8D10-F3CCE9C58B2C} = {A1967865-8F3B-4976-A7EC-8F91EAE4C964}
{5A71211F-9EDA-4C43-8DDC-E3EB54843113} = {A1967865-8F3B-4976-A7EC-8F91EAE4C964}
{28586359-004C-45B5-823E-38F714784B31} = {A1967865-8F3B-4976-A7EC-8F91EAE4C964}
+ {19ED33D1-7D07-43ED-878A-16630CD4035D} = {A1967865-8F3B-4976-A7EC-8F91EAE4C964}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {ECBBFB65-D6D1-4727-BE82-54D52CE8FCF3}
diff --git a/Source/SharpVectorConvertersWpf/Shapes/ShapeRenderingVisitor.cs b/Source/SharpVectorConvertersWpf/Shapes/ShapeRenderingVisitor.cs
index deea47c0d..2187499e4 100644
--- a/Source/SharpVectorConvertersWpf/Shapes/ShapeRenderingVisitor.cs
+++ b/Source/SharpVectorConvertersWpf/Shapes/ShapeRenderingVisitor.cs
@@ -335,7 +335,7 @@ public void Visit(ISvgTextElement element)
}
else if (TryCast.Cast(child, out simpleText))
{
- geometry = ConstructTextGeometry(element as SvgTextElement,
+ geometry = ConstructTextGeometry(element as SvgTextBaseElement,
simpleText.InnerText, position, out spanSize);
shape = WrapGeometry(geometry, element);
shape.IsHitTestVisible = false;
diff --git a/Source/SharpVectorCore/SharpVectors.Core.csproj b/Source/SharpVectorCore/SharpVectors.Core.csproj
index 185fc497b..028c169cd 100644
--- a/Source/SharpVectorCore/SharpVectors.Core.csproj
+++ b/Source/SharpVectorCore/SharpVectors.Core.csproj
@@ -111,6 +111,9 @@
+
+
+
@@ -482,15 +485,6 @@
Code
-
- Code
-
-
- Code
-
-
- Code
-
Code
diff --git a/Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISharpMarkerHost.cs b/Source/SharpVectorCore/Svg/ClippingMasking/ISharpMarkerHost.cs
similarity index 96%
rename from Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISharpMarkerHost.cs
rename to Source/SharpVectorCore/Svg/ClippingMasking/ISharpMarkerHost.cs
index 33119bb34..ed5b9429e 100644
--- a/Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISharpMarkerHost.cs
+++ b/Source/SharpVectorCore/Svg/ClippingMasking/ISharpMarkerHost.cs
@@ -1,64 +1,64 @@
-namespace SharpVectors.Dom.Svg
-{
- ///
- /// This is an extension to the Svg DOM. It denotes that an element can display markers.
- ///
- ///
- ///
- /// A marker is a symbol which is attached to one or more vertices of some Svg elements. In order for
- /// a marker to be drawn correctly, its orientation and position needs to be known.
- /// See SVG 1.0 Masking - Establishing A New Clipping Path
- ///
- ///
- /// This interface provides the information required to calculate the
- /// orientation and position for each marker of an Svg element.
- ///
- ///
- /// To give an Svg element the capability to draw markers, let the Svg element implement this interface.
- ///
- ///
- public interface ISharpMarkerHost
- {
- ///
- /// An array specifying the position of each vertex in the Svg element's shape.
- ///
- SvgPointF[] MarkerPositions
- {
- get;
- }
-
- bool IsClosed
- {
- get;
- }
-
- bool MayHaveCurves
- {
- get;
- }
-
- ISvgMarker GetMarker(int index);
-
- ///
- /// Get the angle of the path segment entering the specified vertex.
- ///
- ///
- /// Specifies the vertex to which the path segment is entering.
- ///
- ///
- /// The angle of the path segment entering the specified vertex in degrees.
- ///
- double GetStartAngle(int index);
-
- ///
- /// Get the angle of the path segment leaving the specified vertex in degrees.
- ///
- ///
- /// Specifies the vertex from which the path segment is leaving.
- ///
- ///
- /// The angle of the path segment leaving the specified vertex.
- ///
- double GetEndAngle(int index);
- }
-}
+namespace SharpVectors.Dom.Svg
+{
+ ///
+ /// This is an extension to the Svg DOM. It denotes that an element can display markers.
+ ///
+ ///
+ ///
+ /// A marker is a symbol which is attached to one or more vertices of some Svg elements. In order for
+ /// a marker to be drawn correctly, its orientation and position needs to be known.
+ /// See SVG 1.0 Masking - Establishing A New Clipping Path
+ ///
+ ///
+ /// This interface provides the information required to calculate the
+ /// orientation and position for each marker of an Svg element.
+ ///
+ ///
+ /// To give an Svg element the capability to draw markers, let the Svg element implement this interface.
+ ///
+ ///
+ public interface ISharpMarkerHost
+ {
+ ///
+ /// An array specifying the position of each vertex in the Svg element's shape.
+ ///
+ SvgPointF[] MarkerPositions
+ {
+ get;
+ }
+
+ bool IsClosed
+ {
+ get;
+ }
+
+ bool MayHaveCurves
+ {
+ get;
+ }
+
+ ISvgMarker GetMarker(int index);
+
+ ///
+ /// Get the angle of the path segment entering the specified vertex.
+ ///
+ ///
+ /// Specifies the vertex to which the path segment is entering.
+ ///
+ ///
+ /// The angle of the path segment entering the specified vertex in degrees.
+ ///
+ double GetStartAngle(int index);
+
+ ///
+ /// Get the angle of the path segment leaving the specified vertex in degrees.
+ ///
+ ///
+ /// Specifies the vertex from which the path segment is leaving.
+ ///
+ ///
+ /// The angle of the path segment leaving the specified vertex.
+ ///
+ double GetEndAngle(int index);
+ }
+}
diff --git a/Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISvgClipPathElement.cs b/Source/SharpVectorCore/Svg/ClippingMasking/ISvgClipPathElement.cs
similarity index 96%
rename from Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISvgClipPathElement.cs
rename to Source/SharpVectorCore/Svg/ClippingMasking/ISvgClipPathElement.cs
index 384c24689..a89a5562e 100644
--- a/Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISvgClipPathElement.cs
+++ b/Source/SharpVectorCore/Svg/ClippingMasking/ISvgClipPathElement.cs
@@ -1,11 +1,11 @@
-namespace SharpVectors.Dom.Svg
-{
- ///
- /// Used by SvgClipPathElement.
- ///
- public interface ISvgClipPathElement : ISvgElement, ISvgTests, ISvgLangSpace,
- ISvgExternalResourcesRequired, ISvgStylable, ISvgTransformable
- {
- ISvgAnimatedEnumeration ClipPathUnits {get;}
- }
-}
+namespace SharpVectors.Dom.Svg
+{
+ ///
+ /// Used by SvgClipPathElement.
+ ///
+ public interface ISvgClipPathElement : ISvgElement, ISvgTests, ISvgLangSpace,
+ ISvgExternalResourcesRequired, ISvgStylable, ISvgTransformable
+ {
+ ISvgAnimatedEnumeration ClipPathUnits {get;}
+ }
+}
diff --git a/Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISvgMaskElement.cs b/Source/SharpVectorCore/Svg/ClippingMasking/ISvgMaskElement.cs
similarity index 96%
rename from Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISvgMaskElement.cs
rename to Source/SharpVectorCore/Svg/ClippingMasking/ISvgMaskElement.cs
index a18b8e43a..7d82784f6 100644
--- a/Source/SharpVectorCore/Svg/ClippingMaskingCompositing/ISvgMaskElement.cs
+++ b/Source/SharpVectorCore/Svg/ClippingMasking/ISvgMaskElement.cs
@@ -1,16 +1,16 @@
-namespace SharpVectors.Dom.Svg
-{
- ///
- /// Used by SvgMaskElement.
- ///
- public interface ISvgMaskElement : ISvgElement, ISvgTests, ISvgLangSpace,
- ISvgExternalResourcesRequired, ISvgStylable
- {
- ISvgAnimatedEnumeration MaskUnits {get;}
- ISvgAnimatedEnumeration MaskContentUnits {get;}
- ISvgAnimatedLength X {get;}
- ISvgAnimatedLength Y {get;}
- ISvgAnimatedLength Width {get;}
- ISvgAnimatedLength Height {get;}
- }
-}
+namespace SharpVectors.Dom.Svg
+{
+ ///
+ /// Used by SvgMaskElement.
+ ///
+ public interface ISvgMaskElement : ISvgElement, ISvgTests, ISvgLangSpace,
+ ISvgExternalResourcesRequired, ISvgStylable
+ {
+ ISvgAnimatedEnumeration MaskUnits {get;}
+ ISvgAnimatedEnumeration MaskContentUnits {get;}
+ ISvgAnimatedLength X {get;}
+ ISvgAnimatedLength Y {get;}
+ ISvgAnimatedLength Width {get;}
+ ISvgAnimatedLength Height {get;}
+ }
+}
diff --git a/Source/SharpVectorModel/BasicTypes/SvgList.cs b/Source/SharpVectorModel/BasicTypes/SvgList.cs
index 82ed3f658..c02f597b7 100644
--- a/Source/SharpVectorModel/BasicTypes/SvgList.cs
+++ b/Source/SharpVectorModel/BasicTypes/SvgList.cs
@@ -4,7 +4,7 @@
/// Note we're using (as opposed to deriving from) to hide unneeded methods
/// Note that a CLR uint is equivalent to an IDL ulong, so uint is used for all index values
///
public abstract class SvgList : IEnumerable
{
#region Private Fields
- protected List _items;
private static IDictionary> _itemOwnerMap;
#endregion
+ protected List _items;
private IDictionary> _itemOwnerMap;
#endregion
#region Constructor
///
/// SvgList constructor
///
protected SvgList()
{
_items = new List();
_itemOwnerMap = new Dictionary>();
}
#endregion
#region ISvgList Interface
///
/// NumberOfItems
///
public uint NumberOfItems
{
get { return (uint) _items.Count; }
}
diff --git a/Source/SharpVectorModel/ClippingMaskingCompositing/SvgClipPathElement.cs b/Source/SharpVectorModel/ClippingMasking/SvgClipPathElement.cs
similarity index 95%
rename from Source/SharpVectorModel/ClippingMaskingCompositing/SvgClipPathElement.cs
rename to Source/SharpVectorModel/ClippingMasking/SvgClipPathElement.cs
index 5cff9be07..d2113f85f 100644
--- a/Source/SharpVectorModel/ClippingMaskingCompositing/SvgClipPathElement.cs
+++ b/Source/SharpVectorModel/ClippingMasking/SvgClipPathElement.cs
@@ -1,119 +1,119 @@
-using System;
-
-namespace SharpVectors.Dom.Svg
-{
- public sealed class SvgClipPathElement : SvgTransformableElement, ISvgClipPathElement
- {
- #region Private Fields
-
- private SvgTests _svgTests;
- private ISvgAnimatedEnumeration _clipPathUnits;
- private SvgExternalResourcesRequired _externalResourcesRequired;
-
- #endregion
-
- #region Constructors and Destructor
-
- public SvgClipPathElement(string prefix, string localname, string ns, SvgDocument doc)
- : base(prefix, localname, ns, doc)
- {
- _externalResourcesRequired = new SvgExternalResourcesRequired(this);
- _svgTests = new SvgTests(this);
- }
-
- #endregion
-
- #region ISvgElement Members
-
- ///
- /// Gets a value indicating whether this SVG element is renderable.
- ///
- ///
- /// This is if the element is renderable; otherwise,
- /// it is .
- ///
- public override bool IsRenderable
- {
- get
- {
- return false;
- }
- }
-
- ///
- /// Gets a value providing a hint on the rendering defined by this element.
- ///
- ///
- /// An enumeration of the specifying the rendering hint.
- /// This will always return
- ///
- public override SvgRenderingHint RenderingHint
- {
- get
- {
- return SvgRenderingHint.Clipping;
- }
- }
-
- #endregion
-
- #region ISvgClipPathElement Members
-
- public ISvgAnimatedEnumeration ClipPathUnits
- {
- get
- {
- if (_clipPathUnits == null)
- {
- SvgUnitType clipPath = SvgUnitType.UserSpaceOnUse;
- if (GetAttribute("clipPathUnits") == "objectBoundingBox")
- {
- clipPath = SvgUnitType.ObjectBoundingBox;
- }
-
- _clipPathUnits = new SvgAnimatedEnumeration((ushort)clipPath);
- }
-
- return _clipPathUnits;
- }
- }
-
- #endregion
-
- #region ISvgExternalResourcesRequired Members
-
- public ISvgAnimatedBoolean ExternalResourcesRequired
- {
- get
- {
- return _externalResourcesRequired.ExternalResourcesRequired;
- }
- }
-
- #endregion
-
- #region ISvgTests Members
-
- public ISvgStringList RequiredFeatures
- {
- get { return _svgTests.RequiredFeatures; }
- }
-
- public ISvgStringList RequiredExtensions
- {
- get { return _svgTests.RequiredExtensions; }
- }
-
- public ISvgStringList SystemLanguage
- {
- get { return _svgTests.SystemLanguage; }
- }
-
- public bool HasExtension(string extension)
- {
- return _svgTests.HasExtension(extension);
- }
-
- #endregion
- }
-}
+using System;
+
+namespace SharpVectors.Dom.Svg
+{
+ public sealed class SvgClipPathElement : SvgTransformableElement, ISvgClipPathElement
+ {
+ #region Private Fields
+
+ private SvgTests _svgTests;
+ private ISvgAnimatedEnumeration _clipPathUnits;
+ private SvgExternalResourcesRequired _externalResourcesRequired;
+
+ #endregion
+
+ #region Constructors and Destructor
+
+ public SvgClipPathElement(string prefix, string localname, string ns, SvgDocument doc)
+ : base(prefix, localname, ns, doc)
+ {
+ _externalResourcesRequired = new SvgExternalResourcesRequired(this);
+ _svgTests = new SvgTests(this);
+ }
+
+ #endregion
+
+ #region ISvgElement Members
+
+ ///
+ /// Gets a value indicating whether this SVG element is renderable.
+ ///
+ ///
+ /// This is if the element is renderable; otherwise,
+ /// it is .
+ ///
+ public override bool IsRenderable
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Gets a value providing a hint on the rendering defined by this element.
+ ///
+ ///
+ /// An enumeration of the specifying the rendering hint.
+ /// This will always return
+ ///
+ public override SvgRenderingHint RenderingHint
+ {
+ get
+ {
+ return SvgRenderingHint.Clipping;
+ }
+ }
+
+ #endregion
+
+ #region ISvgClipPathElement Members
+
+ public ISvgAnimatedEnumeration ClipPathUnits
+ {
+ get
+ {
+ if (_clipPathUnits == null)
+ {
+ SvgUnitType clipPath = SvgUnitType.UserSpaceOnUse;
+ if (GetAttribute("clipPathUnits") == "objectBoundingBox")
+ {
+ clipPath = SvgUnitType.ObjectBoundingBox;
+ }
+
+ _clipPathUnits = new SvgAnimatedEnumeration((ushort)clipPath);
+ }
+
+ return _clipPathUnits;
+ }
+ }
+
+ #endregion
+
+ #region ISvgExternalResourcesRequired Members
+
+ public ISvgAnimatedBoolean ExternalResourcesRequired
+ {
+ get
+ {
+ return _externalResourcesRequired.ExternalResourcesRequired;
+ }
+ }
+
+ #endregion
+
+ #region ISvgTests Members
+
+ public ISvgStringList RequiredFeatures
+ {
+ get { return _svgTests.RequiredFeatures; }
+ }
+
+ public ISvgStringList RequiredExtensions
+ {
+ get { return _svgTests.RequiredExtensions; }
+ }
+
+ public ISvgStringList SystemLanguage
+ {
+ get { return _svgTests.SystemLanguage; }
+ }
+
+ public bool HasExtension(string extension)
+ {
+ return _svgTests.HasExtension(extension);
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/SharpVectorModel/ClippingMaskingCompositing/SvgMaskElement.cs b/Source/SharpVectorModel/ClippingMasking/SvgMaskElement.cs
similarity index 95%
rename from Source/SharpVectorModel/ClippingMaskingCompositing/SvgMaskElement.cs
rename to Source/SharpVectorModel/ClippingMasking/SvgMaskElement.cs
index bbf90d572..3953ca95f 100644
--- a/Source/SharpVectorModel/ClippingMaskingCompositing/SvgMaskElement.cs
+++ b/Source/SharpVectorModel/ClippingMasking/SvgMaskElement.cs
@@ -1,186 +1,186 @@
-using System;
-
-namespace SharpVectors.Dom.Svg
-{
- public sealed class SvgMaskElement : SvgStyleableElement, ISvgMaskElement
- {
- #region Private Fields
-
- private ISvgAnimatedLength _x;
- private ISvgAnimatedLength _y;
- private ISvgAnimatedLength _width;
- private ISvgAnimatedLength _height;
-
- private ISvgAnimatedEnumeration _maskUnits;
- private ISvgAnimatedEnumeration _maskContentUnits;
-
- private SvgTests _svgTests;
- private SvgExternalResourcesRequired _externalResourcesRequired;
-
- #endregion
-
- #region Constructors and Destructor
-
- public SvgMaskElement(string prefix, string localname, string ns, SvgDocument doc)
- : base(prefix, localname, ns, doc)
- {
- _externalResourcesRequired = new SvgExternalResourcesRequired(this);
- _svgTests = new SvgTests(this);
- }
-
- #endregion
-
- #region ISvgElement Members
-
- ///
- /// Gets a value indicating whether this SVG element is renderable.
- ///
- ///
- /// This is if the element is renderable; otherwise,
- /// it is .
- ///
- public override bool IsRenderable
- {
- get
- {
- return false;
- }
- }
-
- ///
- /// Gets a value providing a hint on the rendering defined by this element.
- ///
- ///
- /// An enumeration of the specifying the rendering hint.
- /// This will always return
- ///
- public override SvgRenderingHint RenderingHint
- {
- get
- {
- return SvgRenderingHint.Masking;
- }
- }
-
- #endregion
-
- #region ISvgMaskElement Members
-
- public ISvgAnimatedEnumeration MaskUnits
- {
- get
- {
- if (_maskUnits == null)
- {
- SvgUnitType mask = SvgUnitType.ObjectBoundingBox;
- if (GetAttribute("maskUnits") == "userSpaceOnUse")
- mask = SvgUnitType.UserSpaceOnUse;
-
- _maskUnits = new SvgAnimatedEnumeration((ushort)mask);
- }
- return _maskUnits;
- }
- }
-
- public ISvgAnimatedEnumeration MaskContentUnits
- {
- get
- {
- if(_maskContentUnits == null)
- {
- SvgUnitType maskContent = SvgUnitType.UserSpaceOnUse;
- if (GetAttribute("maskContentUnits") == "objectBoundingBox")
- maskContent = SvgUnitType.ObjectBoundingBox;
- _maskContentUnits = new SvgAnimatedEnumeration((ushort)maskContent);
- }
- return _maskContentUnits;
- }
- }
-
- public ISvgAnimatedLength X
- {
- get
- {
- if (_x == null)
- {
- _x = new SvgAnimatedLength(this, "x", SvgLengthDirection.Horizontal, "-10%");
- }
- return _x;
- }
- }
-
- public ISvgAnimatedLength Y
- {
- get
- {
- if(_y == null)
- {
- _y = new SvgAnimatedLength(this, "y", SvgLengthDirection.Vertical, "-10%");
- }
- return _y;
- }
- }
-
- public ISvgAnimatedLength Width
- {
- get
- {
- if (_width == null)
- {
- _width = new SvgAnimatedLength(this, "width", SvgLengthDirection.Viewport, "120%");
- }
- return _width;
- }
- }
-
- public ISvgAnimatedLength Height
- {
- get
- {
- if (_height == null)
- {
- _height = new SvgAnimatedLength(this, "height", SvgLengthDirection.Viewport, "120%");
- }
- return _height;
- }
- }
-
- #endregion
-
- #region ISvgExternalResourcesRequired Members
-
- public ISvgAnimatedBoolean ExternalResourcesRequired
- {
- get
- {
- return _externalResourcesRequired.ExternalResourcesRequired;
- }
- }
-
- #endregion
-
- #region ISvgTests Members
-
- public ISvgStringList RequiredFeatures
- {
- get { return _svgTests.RequiredFeatures; }
- }
-
- public ISvgStringList RequiredExtensions
- {
- get { return _svgTests.RequiredExtensions; }
- }
-
- public ISvgStringList SystemLanguage
- {
- get { return _svgTests.SystemLanguage; }
- }
-
- public bool HasExtension(string extension)
- {
- return _svgTests.HasExtension(extension);
- }
-
- #endregion
- }
-}
+using System;
+
+namespace SharpVectors.Dom.Svg
+{
+ public sealed class SvgMaskElement : SvgStyleableElement, ISvgMaskElement
+ {
+ #region Private Fields
+
+ private ISvgAnimatedLength _x;
+ private ISvgAnimatedLength _y;
+ private ISvgAnimatedLength _width;
+ private ISvgAnimatedLength _height;
+
+ private ISvgAnimatedEnumeration _maskUnits;
+ private ISvgAnimatedEnumeration _maskContentUnits;
+
+ private SvgTests _svgTests;
+ private SvgExternalResourcesRequired _externalResourcesRequired;
+
+ #endregion
+
+ #region Constructors and Destructor
+
+ public SvgMaskElement(string prefix, string localname, string ns, SvgDocument doc)
+ : base(prefix, localname, ns, doc)
+ {
+ _externalResourcesRequired = new SvgExternalResourcesRequired(this);
+ _svgTests = new SvgTests(this);
+ }
+
+ #endregion
+
+ #region ISvgElement Members
+
+ ///
+ /// Gets a value indicating whether this SVG element is renderable.
+ ///
+ ///
+ /// This is if the element is renderable; otherwise,
+ /// it is .
+ ///
+ public override bool IsRenderable
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Gets a value providing a hint on the rendering defined by this element.
+ ///
+ ///
+ /// An enumeration of the specifying the rendering hint.
+ /// This will always return
+ ///
+ public override SvgRenderingHint RenderingHint
+ {
+ get
+ {
+ return SvgRenderingHint.Masking;
+ }
+ }
+
+ #endregion
+
+ #region ISvgMaskElement Members
+
+ public ISvgAnimatedEnumeration MaskUnits
+ {
+ get
+ {
+ if (_maskUnits == null)
+ {
+ SvgUnitType mask = SvgUnitType.ObjectBoundingBox;
+ if (GetAttribute("maskUnits") == "userSpaceOnUse")
+ mask = SvgUnitType.UserSpaceOnUse;
+
+ _maskUnits = new SvgAnimatedEnumeration((ushort)mask);
+ }
+ return _maskUnits;
+ }
+ }
+
+ public ISvgAnimatedEnumeration MaskContentUnits
+ {
+ get
+ {
+ if(_maskContentUnits == null)
+ {
+ SvgUnitType maskContent = SvgUnitType.UserSpaceOnUse;
+ if (GetAttribute("maskContentUnits") == "objectBoundingBox")
+ maskContent = SvgUnitType.ObjectBoundingBox;
+ _maskContentUnits = new SvgAnimatedEnumeration((ushort)maskContent);
+ }
+ return _maskContentUnits;
+ }
+ }
+
+ public ISvgAnimatedLength X
+ {
+ get
+ {
+ if (_x == null)
+ {
+ _x = new SvgAnimatedLength(this, "x", SvgLengthDirection.Horizontal, "-10%");
+ }
+ return _x;
+ }
+ }
+
+ public ISvgAnimatedLength Y
+ {
+ get
+ {
+ if(_y == null)
+ {
+ _y = new SvgAnimatedLength(this, "y", SvgLengthDirection.Vertical, "-10%");
+ }
+ return _y;
+ }
+ }
+
+ public ISvgAnimatedLength Width
+ {
+ get
+ {
+ if (_width == null)
+ {
+ _width = new SvgAnimatedLength(this, "width", SvgLengthDirection.Viewport, "120%");
+ }
+ return _width;
+ }
+ }
+
+ public ISvgAnimatedLength Height
+ {
+ get
+ {
+ if (_height == null)
+ {
+ _height = new SvgAnimatedLength(this, "height", SvgLengthDirection.Viewport, "120%");
+ }
+ return _height;
+ }
+ }
+
+ #endregion
+
+ #region ISvgExternalResourcesRequired Members
+
+ public ISvgAnimatedBoolean ExternalResourcesRequired
+ {
+ get
+ {
+ return _externalResourcesRequired.ExternalResourcesRequired;
+ }
+ }
+
+ #endregion
+
+ #region ISvgTests Members
+
+ public ISvgStringList RequiredFeatures
+ {
+ get { return _svgTests.RequiredFeatures; }
+ }
+
+ public ISvgStringList RequiredExtensions
+ {
+ get { return _svgTests.RequiredExtensions; }
+ }
+
+ public ISvgStringList SystemLanguage
+ {
+ get { return _svgTests.SystemLanguage; }
+ }
+
+ public bool HasExtension(string extension)
+ {
+ return _svgTests.HasExtension(extension);
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/SharpVectorModel/Diagrams/SvgTextContentElements.cd b/Source/SharpVectorModel/Diagrams/SvgTextContentElements.cd
index da0aba960..32ae72e72 100644
--- a/Source/SharpVectorModel/Diagrams/SvgTextContentElements.cd
+++ b/Source/SharpVectorModel/Diagrams/SvgTextContentElements.cd
@@ -3,8 +3,8 @@
- ACEAAAAFCBAAoCAIACEgQABAQAABAABgAAoARAEFgAQ=
- Dom\Svg\Text\SvgTextContentElement.cs
+ ACEAEIAFCAAAICAAAAUhAABAQAAAAABAAAAARAAEgAQ=
+ Text\SvgTextContentElement.cs
@@ -12,39 +12,47 @@
AAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAYAA=
- Dom\Svg\Text\SvgTextPositioningElement.cs
+ Text\SvgTextPositioningElement.cs
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA=
- Dom\Svg\Text\SvgTextElement.cs
+ AIAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAABAAAAAA=
+ Text\SvgTextElement.cs
- AAAAAAAAAAAAAAAIAAAAIAAAAAAAAABAABAAAAABAAA=
- Dom\Svg\Text\SvgTRefElement.cs
+ AAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAABAAAAAAAAA=
+ Text\SvgTRefElement.cs
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- Dom\Svg\Text\SvgTSpanElement.cs
+ AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
+ Text\SvgTSpanElement.cs
+
+
+
+ AIAAQAAAAAAAAAAAAAAgAAAAAEAAAABAABAABAAAgAA=
+ Text\SvgTextPathElement.cs
+
+
+
AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBA=
- Dom\Svg\Text\SvgTextContentElement.cs
+ Text\SvgTextContentElement.cs
diff --git a/Source/SharpVectorModel/DocumentStructure/SvgDocument.cs b/Source/SharpVectorModel/DocumentStructure/SvgDocument.cs
index 191e4ab5e..4b68a2295 100644
--- a/Source/SharpVectorModel/DocumentStructure/SvgDocument.cs
+++ b/Source/SharpVectorModel/DocumentStructure/SvgDocument.cs
@@ -387,7 +387,6 @@ public override void Load(string filename)
this.Load(zipStream);
}
}
-
return;
}
}
@@ -610,10 +609,9 @@ private string OnXmlResolverResolving(string relativeUri)
///
private XmlParserContext GetXmlParserContext()
{
- DynamicXmlNamespaceManager xmlNamespaceManager = new DynamicXmlNamespaceManager(new NameTable());
+ var xmlNamespaceManager = new DynamicXmlNamespaceManager(new NameTable());
xmlNamespaceManager.Resolve += OnResolveXmlNamespaceManager;
- XmlParserContext xmlParserContext = new XmlParserContext(null,
- xmlNamespaceManager, null, XmlSpace.None);
+ XmlParserContext xmlParserContext = new XmlParserContext(null, xmlNamespaceManager, null, XmlSpace.None);
return xmlParserContext;
}
@@ -628,9 +626,9 @@ private string OnResolveXmlNamespaceManager(string prefix)
string uri = null;
if (this.ResolveNamespace != null)
{
- SvgResolveNamespaceEventArgs e = new SvgResolveNamespaceEventArgs(prefix);
- ResolveNamespace(this, e);
- uri = e.Uri;
+ var evtArgs = new SvgResolveNamespaceEventArgs(prefix);
+ ResolveNamespace(this, evtArgs);
+ uri = evtArgs.Uri;
}
if (string.IsNullOrWhiteSpace(uri))
{
@@ -704,11 +702,8 @@ private XmlReader CreateValidatingXmlReader(string uri, Stream stream)
{
return XmlReader.Create(stream, xmlReaderSettings, uri);
}
- else
- {
- XmlParserContext xmlParserContext = GetXmlParserContext();
- return XmlReader.Create(stream, xmlReaderSettings, xmlParserContext);
- }
+ XmlParserContext xmlParserContext = GetXmlParserContext();
+ return XmlReader.Create(stream, xmlReaderSettings, xmlParserContext);
}
///
@@ -739,68 +734,66 @@ public XmlNode GetNodeByUri(string absoluteUrl)
{
return GetElementById(absoluteUrl.Substring(1));
}
- else
- {
- Uri docUri = ResolveUri("");
- Uri absoluteUri = new Uri(absoluteUrl);
- if (absoluteUri.IsFile)
+ Uri docUri = ResolveUri("");
+ Uri absoluteUri = new Uri(absoluteUrl);
+
+ if (absoluteUri.IsFile)
+ {
+ string localFile = absoluteUri.LocalPath;
+ if (File.Exists(localFile) == false)
{
- string localFile = absoluteUri.LocalPath;
- if (File.Exists(localFile) == false)
- {
- Trace.TraceError("GetNodeByUri: Locally referenced file not found: " + localFile);
- return null;
- }
- string fileExt = Path.GetExtension(localFile);
- if (!string.Equals(fileExt, ".svg", StringComparison.OrdinalIgnoreCase)
- && !string.Equals(fileExt, ".svgz", StringComparison.OrdinalIgnoreCase))
- {
- Trace.TraceError("GetNodeByUri: Locally referenced file not valid: " + localFile);
- return null;
- }
+ Trace.TraceError("GetNodeByUri: Locally referenced file not found: " + localFile);
+ return null;
}
-
- if (string.Equals(absoluteUri.Scheme, "data", StringComparison.OrdinalIgnoreCase))
+ string fileExt = Path.GetExtension(localFile);
+ if (!string.Equals(fileExt, ".svg", StringComparison.OrdinalIgnoreCase)
+ && !string.Equals(fileExt, ".svgz", StringComparison.OrdinalIgnoreCase))
{
- Trace.TraceError("GetNodeByUri: The Uri Scheme is 'data' is not a valid XmlDode " + absoluteUri);
+ Trace.TraceError("GetNodeByUri: Locally referenced file not valid: " + localFile);
return null;
}
+ }
+
+ if (string.Equals(absoluteUri.Scheme, "data", StringComparison.OrdinalIgnoreCase))
+ {
+ Trace.TraceError("GetNodeByUri: The Uri Scheme is 'data' is not a valid XmlDode " + absoluteUri);
+ return null;
+ }
- string fragment = absoluteUri.Fragment;
+ string fragment = absoluteUri.Fragment;
- if (fragment.Length == 0)
+ if (fragment.Length == 0)
+ {
+ // no fragment => return entire document
+ if (docUri != null && string.Equals(docUri.AbsolutePath,
+ absoluteUri.AbsolutePath, StringComparison.OrdinalIgnoreCase))
{
- // no fragment => return entire document
- if (docUri != null && docUri.AbsolutePath == absoluteUri.AbsolutePath)
- {
- return this;
- }
-
- SvgDocument doc = new SvgDocument((SvgWindow)Window);
+ return this;
+ }
- XmlReaderSettings settings = this.GetXmlReaderSettings();
+ SvgDocument doc = new SvgDocument((SvgWindow)Window);
- settings.CloseInput = true;
+ XmlReaderSettings settings = this.GetXmlReaderSettings();
- //PrepareXmlResolver(settings);
+ settings.CloseInput = true;
- using (XmlReader reader = XmlReader.Create(
- GetResource(absoluteUri).GetResponseStream(), settings,
- absoluteUri.AbsolutePath))
- {
- doc.Load(reader);
- }
+ //PrepareXmlResolver(settings);
- return doc;
- }
- else
+ using (XmlReader reader = XmlReader.Create(GetResource(absoluteUri).GetResponseStream(),
+ settings, absoluteUri.AbsolutePath))
{
- // got a fragment => return XmlElement
- string noFragment = absoluteUri.AbsoluteUri.Replace(fragment, "");
- SvgDocument doc = (SvgDocument)GetNodeByUri(new Uri(noFragment));
- return doc.GetElementById(fragment.Substring(1));
+ doc.Load(reader);
}
+
+ return doc;
+ }
+ else
+ {
+ // got a fragment => return XmlElement
+ string noFragment = absoluteUri.AbsoluteUri.Replace(fragment, "");
+ SvgDocument doc = (SvgDocument)GetNodeByUri(new Uri(noFragment));
+ return doc.GetElementById(fragment.Substring(1));
}
}
@@ -1150,7 +1143,8 @@ protected virtual IList> GetFontUrls()
return fontUrls;
}
- private static void GetFontUrl(CssStyleSheet cssSheet, IList> fontUrls, IDictionary styledFontIds)
+ private static void GetFontUrl(CssStyleSheet cssSheet, IList> fontUrls,
+ IDictionary styledFontIds)
{
if (cssSheet == null || fontUrls == null)
{
@@ -1208,7 +1202,7 @@ protected override void OnLoaded()
_isFontsLoaded = false;
//TODO: Trying a background run...
- Task.Factory.StartNew(() => {
+ var loadTask = Task.Factory.StartNew(() => {
SvgWindow ownedWindow = _window.CreateOwnedWindow();
ownedWindow.LoadFonts = false;
@@ -1238,7 +1232,7 @@ protected override void OnLoaded()
}
else
{
- //TODO
+ throw new NotSupportedException("Loading fonts from a remote source is not supported.");
}
}
catch (Exception ex)
@@ -1250,12 +1244,15 @@ protected override void OnLoaded()
_isFontsLoaded = true;
});
+
+ _window.AddTask("SvgDocument", loadTask);
}
private void LoadLocalFont(string fontPath, SvgWindow ownedWindow, SvgFontFaceElement fontFace)
{
if (string.IsNullOrWhiteSpace(fontPath) || !File.Exists(fontPath))
{
+// Trace.WriteLine("Private font not found: " + fontPath);
return;
}
@@ -1289,6 +1286,12 @@ private void LoadLocalFont(string fontPath, SvgWindow ownedWindow, SvgFontFaceEl
else if (string.Equals(fileExt, ".ttf", StringComparison.OrdinalIgnoreCase)
|| string.Equals(fileExt, ".otf", StringComparison.OrdinalIgnoreCase))
{
+ Debug.Assert(false, "Testing files with this format");
+ }
+ else if (string.Equals(fileExt, ".woff", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(fileExt, ".woff2", StringComparison.OrdinalIgnoreCase))
+ {
+ Debug.Assert(false, "Testing files with this format");
}
}
diff --git a/Source/SharpVectorModel/DocumentStructure/SvgElementFactory.cs b/Source/SharpVectorModel/DocumentStructure/SvgElementFactory.cs
index 68653451d..7575f1532 100644
--- a/Source/SharpVectorModel/DocumentStructure/SvgElementFactory.cs
+++ b/Source/SharpVectorModel/DocumentStructure/SvgElementFactory.cs
@@ -67,6 +67,8 @@ public static XmlElement Create(string prefix, string localName, string ns, SvgD
return new SvgSymbolElement(prefix, localName, ns, doc);
case "text":
return new SvgTextElement(prefix, localName, ns, doc);
+ case "textArea":
+ return new SvgTextAreaElement(prefix, localName, ns, doc);
case "textPath":
return new SvgTextPathElement(prefix, localName, ns, doc);
case "title":
diff --git a/Source/SharpVectorModel/DocumentStructure/SvgWindow.cs b/Source/SharpVectorModel/DocumentStructure/SvgWindow.cs
index cf0304d63..1c71ee73f 100644
--- a/Source/SharpVectorModel/DocumentStructure/SvgWindow.cs
+++ b/Source/SharpVectorModel/DocumentStructure/SvgWindow.cs
@@ -1,6 +1,8 @@
using System;
using System.IO;
using System.Xml;
+using System.Threading.Tasks;
+using System.Collections.Generic;
using SharpVectors.Dom.Stylesheets;
@@ -10,6 +12,8 @@ public abstract class SvgWindow : ISvgWindow
{
#region Private fields
+ protected IDictionary> _mappedTasks;
+
private bool _loadFonts;
private long _innerWidth;
@@ -19,12 +23,15 @@ public abstract class SvgWindow : ISvgWindow
private ISvgRenderer _renderer;
+ private object _synchObject;
+
#endregion
#region Contructors and Destructor
private SvgWindow()
{
+ _synchObject = new object();
}
protected SvgWindow(long innerWidth, long innerHeight, ISvgRenderer renderer)
@@ -93,6 +100,60 @@ public SvgDocument CreateEmptySvgDocument()
return _document = new SvgDocument(this);
}
+ public void AddTask(string tasksName, Task task)
+ {
+ if (string.IsNullOrWhiteSpace(tasksName) || task == null)
+ {
+ return;
+ }
+ lock (_synchObject)
+ {
+ if (_mappedTasks == null)
+ {
+ _mappedTasks = new Dictionary>(StringComparer.OrdinalIgnoreCase);
+ }
+ if (_mappedTasks.ContainsKey(tasksName))
+ {
+ var namedTasks = _mappedTasks[tasksName];
+ if (namedTasks == null)
+ {
+ namedTasks = new List();
+ }
+ namedTasks.Add(task);
+ }
+ else
+ {
+ var namedTasks = new List();
+ namedTasks.Add(task);
+
+ _mappedTasks.Add(tasksName, namedTasks);
+ }
+ }
+ }
+
+ public void AwaitTasks(string tasksName)
+ {
+ lock (_synchObject)
+ {
+ if (string.IsNullOrWhiteSpace(tasksName) || _mappedTasks == null || _mappedTasks.Count == 0)
+ {
+ return;
+ }
+ if (_mappedTasks.ContainsKey(tasksName))
+ {
+ var namedTasks = _mappedTasks[tasksName];
+ if (namedTasks == null || namedTasks.Count == 0)
+ {
+ return;
+ }
+
+ Task.WaitAll(namedTasks.ToArray());
+
+ _mappedTasks.Remove(tasksName);
+ }
+ }
+ }
+
#endregion
#region ISvgWindow Members
diff --git a/Source/SharpVectorModel/SharpVectors.Model.csproj b/Source/SharpVectorModel/SharpVectors.Model.csproj
index a874747ea..2b7c023cc 100644
--- a/Source/SharpVectorModel/SharpVectors.Model.csproj
+++ b/Source/SharpVectorModel/SharpVectors.Model.csproj
@@ -123,6 +123,8 @@
+
+
@@ -240,12 +242,6 @@
Code
-
- Code
-
-
- Code
-
Code
@@ -447,10 +443,12 @@
+
Code
-
+
+
Code
diff --git a/Source/SharpVectorModel/Text/SvgAltGlyphElement.cs b/Source/SharpVectorModel/Text/SvgAltGlyphElement.cs
index 7247306c8..fddf565a7 100644
--- a/Source/SharpVectorModel/Text/SvgAltGlyphElement.cs
+++ b/Source/SharpVectorModel/Text/SvgAltGlyphElement.cs
@@ -1,8 +1,5 @@
using System;
using System.Xml;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace SharpVectors.Dom.Svg
{
diff --git a/Source/SharpVectorModel/Text/SvgFontFaceFormatElement.cs b/Source/SharpVectorModel/Text/SvgFontFaceFormatElement.cs
index cbb9e4056..8c7a49b7e 100644
--- a/Source/SharpVectorModel/Text/SvgFontFaceFormatElement.cs
+++ b/Source/SharpVectorModel/Text/SvgFontFaceFormatElement.cs
@@ -1,4 +1,6 @@
-namespace SharpVectors.Dom.Svg
+using System;
+
+namespace SharpVectors.Dom.Svg
{
///
/// The SvgFontFaceFormatElement interface corresponds to the 'font-face-format' element.
diff --git a/Source/SharpVectorModel/Text/SvgFontFaceNameElement.cs b/Source/SharpVectorModel/Text/SvgFontFaceNameElement.cs
index 06dc5dfca..88d6f8510 100644
--- a/Source/SharpVectorModel/Text/SvgFontFaceNameElement.cs
+++ b/Source/SharpVectorModel/Text/SvgFontFaceNameElement.cs
@@ -1,4 +1,6 @@
-namespace SharpVectors.Dom.Svg
+using System;
+
+namespace SharpVectors.Dom.Svg
{
///
/// The SvgFontFaceNameElement interface corresponds to the 'font-face-name' element.
diff --git a/Source/SharpVectorModel/Text/SvgFontFaceUriElement.cs b/Source/SharpVectorModel/Text/SvgFontFaceUriElement.cs
index 69d78b993..074ec06bb 100644
--- a/Source/SharpVectorModel/Text/SvgFontFaceUriElement.cs
+++ b/Source/SharpVectorModel/Text/SvgFontFaceUriElement.cs
@@ -1,4 +1,6 @@
-namespace SharpVectors.Dom.Svg
+using System;
+
+namespace SharpVectors.Dom.Svg
{
///
/// The SvgFontFaceUriElement interface corresponds to the 'font-face-uri' element.
diff --git a/Source/SharpVectorModel/Text/SvgGlyphRefElement.cs b/Source/SharpVectorModel/Text/SvgGlyphRefElement.cs
index cbab01c3a..83ff98fee 100644
--- a/Source/SharpVectorModel/Text/SvgGlyphRefElement.cs
+++ b/Source/SharpVectorModel/Text/SvgGlyphRefElement.cs
@@ -1,4 +1,5 @@
-using System.Xml;
+using System;
+using System.Xml;
namespace SharpVectors.Dom.Svg
{
diff --git a/Source/SharpVectorModel/Text/SvgHKernElement.cs b/Source/SharpVectorModel/Text/SvgHKernElement.cs
index 261fc6710..2ad255d8e 100644
--- a/Source/SharpVectorModel/Text/SvgHKernElement.cs
+++ b/Source/SharpVectorModel/Text/SvgHKernElement.cs
@@ -1,4 +1,6 @@
-namespace SharpVectors.Dom.Svg
+using System;
+
+namespace SharpVectors.Dom.Svg
{
///
/// The SvgHKernElement interface corresponds to the 'hkern' element.
diff --git a/Source/SharpVectorModel/Text/SvgKernElement.cs b/Source/SharpVectorModel/Text/SvgKernElement.cs
index 0eca6e8a1..e4d28922f 100644
--- a/Source/SharpVectorModel/Text/SvgKernElement.cs
+++ b/Source/SharpVectorModel/Text/SvgKernElement.cs
@@ -1,7 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace SharpVectors.Dom.Svg
{
diff --git a/Source/SharpVectorModel/Text/SvgMissingGlyphElement.cs b/Source/SharpVectorModel/Text/SvgMissingGlyphElement.cs
index d455982e1..4b005ed9f 100644
--- a/Source/SharpVectorModel/Text/SvgMissingGlyphElement.cs
+++ b/Source/SharpVectorModel/Text/SvgMissingGlyphElement.cs
@@ -1,4 +1,6 @@
-namespace SharpVectors.Dom.Svg
+using System;
+
+namespace SharpVectors.Dom.Svg
{
///
/// The SvgMissingGlyphElement interface corresponds to the 'missing-glyph' element.
diff --git a/Source/SharpVectorModel/Text/SvgTextAreaElement.cs b/Source/SharpVectorModel/Text/SvgTextAreaElement.cs
new file mode 100644
index 000000000..95328d539
--- /dev/null
+++ b/Source/SharpVectorModel/Text/SvgTextAreaElement.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace SharpVectors.Dom.Svg
+{
+ ///
+ /// Summary description for SvgTextAreaElement.
+ ///
+ public sealed class SvgTextAreaElement : SvgTextBaseElement, ISvgTextElement
+ {
+ public SvgTextAreaElement(string prefix, string localname, string ns, SvgDocument doc)
+ : base(prefix, localname, ns, doc)
+ {
+ }
+ }
+}
diff --git a/Source/SharpVectorModel/Text/SvgTextBaseElement.cs b/Source/SharpVectorModel/Text/SvgTextBaseElement.cs
new file mode 100644
index 000000000..4f1996cb4
--- /dev/null
+++ b/Source/SharpVectorModel/Text/SvgTextBaseElement.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace SharpVectors.Dom.Svg
+{
+ ///
+ /// Summary description for SvgTextElement.
+ ///
+ public abstract class SvgTextBaseElement : SvgTextPositioningElement, ISvgTextElement
+ {
+ protected SvgTextBaseElement(string prefix, string localname, string ns, SvgDocument doc)
+ : base(prefix, localname, ns, doc)
+ {
+ }
+
+ public override ISvgAnimatedLength LetterSpacing
+ {
+ get {
+ return new SvgAnimatedLength(this, "letter-spacing", SvgLengthDirection.Horizontal, "0");
+ }
+ }
+
+ public override ISvgAnimatedLength TextLength
+ {
+ get {
+ return new SvgAnimatedLength(this, "textLength", SvgLengthDirection.Horizontal, "0");
+ }
+ }
+
+ #region Implementation of IElementVisitorTarget
+
+ public void Accept(IElementVisitor visitor)
+ {
+ visitor.Visit(this);
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/SharpVectorModel/Text/SvgTextContentElement.cs b/Source/SharpVectorModel/Text/SvgTextContentElement.cs
index 830c22dbd..01dbda846 100644
--- a/Source/SharpVectorModel/Text/SvgTextContentElement.cs
+++ b/Source/SharpVectorModel/Text/SvgTextContentElement.cs
@@ -102,13 +102,13 @@ public virtual ISvgAnimatedEnumeration LengthAdjust
get { throw new NotImplementedException(); }
}
- protected SvgTextElement OwnerTextElement
+ protected SvgTextBaseElement OwnerTextElement
{
get {
XmlNode node = this;
while (node != null)
{
- SvgTextElement text = node as SvgTextElement;
+ SvgTextBaseElement text = node as SvgTextBaseElement;
if (text != null)
{
return text;
diff --git a/Source/SharpVectorModel/Text/SvgTextElement.cs b/Source/SharpVectorModel/Text/SvgTextElement.cs
index fbdd35599..b08b70638 100644
--- a/Source/SharpVectorModel/Text/SvgTextElement.cs
+++ b/Source/SharpVectorModel/Text/SvgTextElement.cs
@@ -5,35 +5,11 @@ namespace SharpVectors.Dom.Svg
///
/// Summary description for SvgTextElement.
///
- public sealed class SvgTextElement : SvgTextPositioningElement, ISvgTextElement
+ public sealed class SvgTextElement : SvgTextBaseElement, ISvgTextElement
{
public SvgTextElement(string prefix, string localname, string ns, SvgDocument doc)
: base(prefix, localname, ns, doc)
{
}
-
-
- public override ISvgAnimatedLength LetterSpacing
- {
- get {
- return new SvgAnimatedLength(this, "letter-spacing", SvgLengthDirection.Horizontal, "0");
- }
- }
-
- public override ISvgAnimatedLength TextLength
- {
- get {
- return new SvgAnimatedLength(this, "textLength", SvgLengthDirection.Horizontal, "0");
- }
- }
-
- #region Implementation of IElementVisitorTarget
-
- public void Accept(IElementVisitor visitor)
- {
- visitor.Visit(this);
- }
-
- #endregion
}
}
diff --git a/Source/SharpVectorModel/Text/SvgVKernElement.cs b/Source/SharpVectorModel/Text/SvgVKernElement.cs
index c177758f8..09a631de3 100644
--- a/Source/SharpVectorModel/Text/SvgVKernElement.cs
+++ b/Source/SharpVectorModel/Text/SvgVKernElement.cs
@@ -1,4 +1,6 @@
-namespace SharpVectors.Dom.Svg
+using System;
+
+namespace SharpVectors.Dom.Svg
{
///
/// The SvgVKernElement interface corresponds to the 'vkern' element.
diff --git a/Source/SharpVectorRenderingGdi/Gdi/GdiTextRendering.cs b/Source/SharpVectorRenderingGdi/Gdi/GdiTextRendering.cs
index fe59f2792..a371a4746 100644
--- a/Source/SharpVectorRenderingGdi/Gdi/GdiTextRendering.cs
+++ b/Source/SharpVectorRenderingGdi/Gdi/GdiTextRendering.cs
@@ -118,7 +118,7 @@ public override void Render(GdiGraphicsRenderer renderer)
// return;
//}
- SvgTextElement textElement = _svgElement as SvgTextElement;
+ SvgTextBaseElement textElement = _svgElement as SvgTextBaseElement;
if (textElement == null)
{
return;
@@ -373,7 +373,7 @@ private void AddTSpanElementPath(SvgTSpanElement element, ref PointF ctp)
if (sBaselineShift.Length > 0)
{
- SvgTextElement textElement = (SvgTextElement)element.SelectSingleNode("ancestor::svg:text",
+ SvgTextBaseElement textElement = (SvgTextBaseElement)element.SelectSingleNode("ancestor::svg:text",
element.OwnerDocument.NamespaceManager);
float textFontSize = GetComputedFontSize(textElement);
diff --git a/Source/SharpVectorRenderingWpf/Texts/WpfHorzTextRenderer.cs b/Source/SharpVectorRenderingWpf/Texts/WpfHorzTextRenderer.cs
index ddbe9164c..ae385dfe2 100644
--- a/Source/SharpVectorRenderingWpf/Texts/WpfHorzTextRenderer.cs
+++ b/Source/SharpVectorRenderingWpf/Texts/WpfHorzTextRenderer.cs
@@ -17,7 +17,7 @@ public sealed class WpfHorzTextRenderer : WpfTextRenderer
#region Constructors and Destructor
- public WpfHorzTextRenderer(SvgTextElement textElement, WpfTextRendering textRendering)
+ public WpfHorzTextRenderer(SvgTextBaseElement textElement, WpfTextRendering textRendering)
: base(textElement, textRendering)
{
}
@@ -371,7 +371,7 @@ public override void RenderTextRun(SvgTextContentElement element, ref Point ctp,
TextDecorationCollection textDecors = GetTextDecoration(element);
if (textDecors == null)
{
- SvgTextElement textElement = element.ParentNode as SvgTextElement;
+ SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement;
if (textElement != null)
{
@@ -911,7 +911,7 @@ private void RenderTextRun(WpfTextTuple textInfo, ref Point ctp,
TextDecorationCollection textDecors = GetTextDecoration(element);
if (textDecors == null)
{
- SvgTextElement textElement = element.ParentNode as SvgTextElement;
+ SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement;
if (textElement != null)
{
diff --git a/Source/SharpVectorRenderingWpf/Texts/WpfPathTextBuilder.cs b/Source/SharpVectorRenderingWpf/Texts/WpfPathTextBuilder.cs
index 497cd5aab..200daaae5 100644
--- a/Source/SharpVectorRenderingWpf/Texts/WpfPathTextBuilder.cs
+++ b/Source/SharpVectorRenderingWpf/Texts/WpfPathTextBuilder.cs
@@ -24,7 +24,7 @@ public sealed class WpfPathTextBuilder
private IList _pathChars;
- private SvgTextElement _textElement;
+ private SvgTextBaseElement _textElement;
private SvgTextPathElement _textPathElement;
private IList _pathTextRuns;
@@ -33,7 +33,7 @@ public sealed class WpfPathTextBuilder
#region Constructors and Destructor
- public WpfPathTextBuilder(SvgTextElement textElement)
+ public WpfPathTextBuilder(SvgTextBaseElement textElement)
{
_textElement = textElement;
_pathChars = new List();
diff --git a/Source/SharpVectorRenderingWpf/Texts/WpfPathTextRenderer.cs b/Source/SharpVectorRenderingWpf/Texts/WpfPathTextRenderer.cs
index c2db5517e..c530f2de5 100644
--- a/Source/SharpVectorRenderingWpf/Texts/WpfPathTextRenderer.cs
+++ b/Source/SharpVectorRenderingWpf/Texts/WpfPathTextRenderer.cs
@@ -17,7 +17,7 @@ public sealed class WpfPathTextRenderer : WpfTextRenderer
#region Constructors and Destructor
- public WpfPathTextRenderer(SvgTextElement textElement, WpfTextRendering textRendering)
+ public WpfPathTextRenderer(SvgTextBaseElement textElement, WpfTextRendering textRendering)
: base(textElement, textRendering)
{
}
@@ -194,7 +194,7 @@ private void RenderTSpanPath(SvgTSpanElement element, WpfPathTextBuilder pathBui
if (sBaselineShift.Length > 0)
{
- SvgTextElement textElement = (SvgTextElement)element.SelectSingleNode("ancestor::svg:text",
+ SvgTextBaseElement textElement = (SvgTextBaseElement)element.SelectSingleNode("ancestor::svg:text",
element.OwnerDocument.NamespaceManager);
double textFontSize = GetComputedFontSize(textElement);
diff --git a/Source/SharpVectorRenderingWpf/Texts/WpfPathTextRun.cs b/Source/SharpVectorRenderingWpf/Texts/WpfPathTextRun.cs
index 1222ccf3a..9bf5ac5eb 100644
--- a/Source/SharpVectorRenderingWpf/Texts/WpfPathTextRun.cs
+++ b/Source/SharpVectorRenderingWpf/Texts/WpfPathTextRun.cs
@@ -105,7 +105,7 @@ public void Initialize(string text, Brush brush, Pen pen)
}
}
- public void SetPosition(Point pos, SvgTextPathElement pathElement, SvgTextElement textElement)
+ public void SetPosition(Point pos, SvgTextPathElement pathElement, SvgTextBaseElement textElement)
{
_contentPos = pos;
_startOffset = this.GetStartOffset(pathElement, textElement);
@@ -148,7 +148,7 @@ public void UnInitialize()
#region Private Methods
- private ISvgAnimatedLength GetStartOffset(SvgTextPathElement pathElement, SvgTextElement textElement)
+ private ISvgAnimatedLength GetStartOffset(SvgTextPathElement pathElement, SvgTextBaseElement textElement)
{
ISvgAnimatedLength pathOffset = pathElement.StartOffset;
if (pathOffset != null && pathOffset.AnimVal != null)
@@ -170,7 +170,7 @@ private ISvgAnimatedLength GetStartOffset(SvgTextPathElement pathElement, SvgTex
return this.GetStartOffset(textElement);
}
- private ISvgAnimatedLength GetStartOffset(SvgTextElement textElement)
+ private ISvgAnimatedLength GetStartOffset(SvgTextBaseElement textElement)
{
ISvgAnimatedLengthList pathOffsets = null;
SvgTextPositioningElement posElement = _contentElement as SvgTextPositioningElement;
diff --git a/Source/SharpVectorRenderingWpf/Texts/WpfTextContext.cs b/Source/SharpVectorRenderingWpf/Texts/WpfTextContext.cs
index b5b15ff4e..54233da92 100644
--- a/Source/SharpVectorRenderingWpf/Texts/WpfTextContext.cs
+++ b/Source/SharpVectorRenderingWpf/Texts/WpfTextContext.cs
@@ -28,7 +28,7 @@ public sealed class WpfTextContext
private Point _positioningEnd;
private SvgTextContentElement _positioningElement;
- private SvgTextElement _textElement;
+ private SvgTextBaseElement _textElement;
private WpfTextRendering _textRendering;
private CultureInfo _culture;
@@ -39,7 +39,7 @@ public sealed class WpfTextContext
#region Constructors and Destructor
- public WpfTextContext(SvgTextElement textElement, WpfTextRendering textRendering)
+ public WpfTextContext(SvgTextBaseElement textElement, WpfTextRendering textRendering)
{
if (textRendering == null)
{
@@ -55,7 +55,7 @@ public WpfTextContext(SvgTextElement textElement, WpfTextRendering textRendering
#region Public Properties
- public SvgTextElement TextElement
+ public SvgTextBaseElement TextElement
{
get {
return _textElement;
@@ -134,7 +134,7 @@ public CultureInfo Culture
#region Public Methods
- public void SetElement(SvgTextElement textElement)
+ public void SetElement(SvgTextBaseElement textElement)
{
if (textElement == null)
{
diff --git a/Source/SharpVectorRenderingWpf/Texts/WpfTextRenderer.cs b/Source/SharpVectorRenderingWpf/Texts/WpfTextRenderer.cs
index f5dc61469..1dd32a270 100644
--- a/Source/SharpVectorRenderingWpf/Texts/WpfTextRenderer.cs
+++ b/Source/SharpVectorRenderingWpf/Texts/WpfTextRenderer.cs
@@ -32,7 +32,7 @@ public abstract class WpfTextRenderer : WpfRendererObject
protected string _actualFontName;
protected DrawingContext _drawContext;
- protected SvgTextElement _textElement;
+ protected SvgTextBaseElement _textElement;
protected WpfTextRendering _textRendering;
@@ -40,7 +40,7 @@ public abstract class WpfTextRenderer : WpfRendererObject
#region Constructors and Destructor
- protected WpfTextRenderer(SvgTextElement textElement, WpfTextRendering textRendering)
+ protected WpfTextRenderer(SvgTextBaseElement textElement, WpfTextRendering textRendering)
{
if (textElement == null)
{
@@ -75,7 +75,7 @@ public DrawingContext DrawContext
}
}
- public SvgTextElement TextElement
+ public SvgTextBaseElement TextElement
{
get {
return _textElement;
@@ -158,7 +158,7 @@ protected WpfTextContext TextContext
#region Public Methods
- public virtual void SetElement(SvgTextElement textElement)
+ public virtual void SetElement(SvgTextBaseElement textElement)
{
_drawContext = null;
_context = null;
@@ -202,6 +202,28 @@ public static string TrimText(SvgTextContentElement element, string val)
val = val.Replace("\n", string.Empty);
val = _tabNewline.Replace(val, " ");
+ var textTransform = element.GetPropertyValue("text-transform");
+ if (!string.IsNullOrWhiteSpace(textTransform))
+ {
+ switch (textTransform)
+ {
+ case "capitalize":
+ val = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(val);
+ break;
+ case "uppercase":
+ val = val.ToUpper(CultureInfo.CurrentCulture);
+ break;
+ case "lowercase":
+ val = val.ToLower(CultureInfo.CurrentCulture);
+ break;
+ case "full-width":
+ case "full-size-kana":
+ case "none":
+ default:
+ break;
+ }
+ }
+
//if (element.XmlSpace == "preserve" || element.XmlSpace == "default")
if (element.XmlSpace == "preserve")
{
@@ -1071,7 +1093,7 @@ protected WpfTextStringFormat GetTextStringFormat(SvgTextContentElement element)
}
else
{
- SvgTextElement textElement = element.ParentNode as SvgTextElement;
+ SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement;
if (textElement != null)
{
string anchor = textElement.GetPropertyValue("text-anchor");
diff --git a/Source/SharpVectorRenderingWpf/Texts/WpfVertTextRenderer.cs b/Source/SharpVectorRenderingWpf/Texts/WpfVertTextRenderer.cs
index 4ea80d9a1..6f59d5209 100644
--- a/Source/SharpVectorRenderingWpf/Texts/WpfVertTextRenderer.cs
+++ b/Source/SharpVectorRenderingWpf/Texts/WpfVertTextRenderer.cs
@@ -18,7 +18,7 @@ public sealed class WpfVertTextRenderer : WpfTextRenderer
#region Constructors and Destructor
- public WpfVertTextRenderer(SvgTextElement textElement, WpfTextRendering textRendering)
+ public WpfVertTextRenderer(SvgTextBaseElement textElement, WpfTextRendering textRendering)
: base(textElement, textRendering)
{
}
diff --git a/Source/SharpVectorRenderingWpf/Wpf/WpfSvgRendering.cs b/Source/SharpVectorRenderingWpf/Wpf/WpfSvgRendering.cs
index 4ee853d12..2f90d0406 100644
--- a/Source/SharpVectorRenderingWpf/Wpf/WpfSvgRendering.cs
+++ b/Source/SharpVectorRenderingWpf/Wpf/WpfSvgRendering.cs
@@ -224,8 +224,37 @@ public override void Render(WpfDrawingRenderer renderer)
public override void AfterRender(WpfDrawingRenderer renderer)
{
+ this.OnAfterRender(renderer);
+
base.AfterRender(renderer);
+ }
+
+ #endregion
+
+ #region Protected Methods
+
+ protected override void Initialize(SvgElement element)
+ {
+ base.Initialize(element);
+
+ _isRoot = false;
+ _isRecursive = false;
+
+ var svgRootElm = element as SvgSvgElement;
+ if (svgRootElm != null)
+ {
+ _isRoot = svgRootElm.IsOuterMost;
+ }
+
+ _drawGroup = null;
+ }
+
+ #endregion
+
+ #region Private Methods
+ private void OnAfterRender(WpfDrawingRenderer renderer)
+ {
Debug.Assert(_drawGroup != null);
WpfDrawingContext context = renderer.Context;
@@ -339,25 +368,5 @@ private DrawingGroup CreateOuterGroup()
}
#endregion
-
- #region Protected Methods
-
- protected override void Initialize(SvgElement element)
- {
- base.Initialize(element);
-
- _isRoot = false;
- _isRecursive = false;
-
- var svgRootElm = element as SvgSvgElement;
- if (svgRootElm != null)
- {
- _isRoot = svgRootElm.IsOuterMost;
- }
-
- _drawGroup = null;
- }
-
- #endregion
}
}
diff --git a/Source/SharpVectorRenderingWpf/Wpf/WpfTextRendering.cs b/Source/SharpVectorRenderingWpf/Wpf/WpfTextRendering.cs
index 7cc115ee8..d3544a263 100644
--- a/Source/SharpVectorRenderingWpf/Wpf/WpfTextRendering.cs
+++ b/Source/SharpVectorRenderingWpf/Wpf/WpfTextRendering.cs
@@ -30,7 +30,7 @@ public sealed class WpfTextRendering : WpfRendering
private double _textWidth;
- private SvgTextElement _textElement;
+ private SvgTextBaseElement _textElement;
private DrawingGroup _drawGroup;
private DrawingContext _drawContext;
@@ -48,7 +48,7 @@ public sealed class WpfTextRendering : WpfRendering
public WpfTextRendering(SvgElement element)
: base(element)
{
- _textElement = element as SvgTextElement;
+ _textElement = element as SvgTextBaseElement;
if (_textElement == null)
{
throw new InvalidOperationException();
@@ -275,7 +275,13 @@ public override void Render(WpfDrawingRenderer renderer)
if (svgDoc.IsFontsLoaded == false)
{
//TODO: Use of SpinUntil is known to CPU heavy, but will work for now...
- SpinWait.SpinUntil(() => svgDoc.IsFontsLoaded == true);
+ //SpinWait.SpinUntil(() => svgDoc.IsFontsLoaded == true);
+
+ var svgWnd = svgDoc.Window as SvgWindow;
+ if (svgWnd != null)
+ {
+ svgWnd.AwaitTasks("SvgDocument");
+ }
}
XmlNodeType nodeType = XmlNodeType.None;
@@ -742,7 +748,7 @@ protected override void Initialize(SvgElement element)
_textWidth = 0;
_drawGroup = null;
- _textElement = element as SvgTextElement;
+ _textElement = element as SvgTextBaseElement;
if (_textElement == null)
{
throw new InvalidOperationException();