Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorConverters/FileSvgConverter.cs @ 13783

Last change on this file since 13783 was 12762, checked in by aballeit, 9 years ago

#2283 GUI updates, Tree-chart, MCTS Version 2 (prune leaves)

File size: 22.8 KB
Line 
1using System;
2using System.IO;
3using System.IO.Compression;
4using System.Xml;
5using System.Text;
6
7using System.Windows;
8using System.Windows.Media;
9
10using SharpVectors.Dom.Svg;
11using SharpVectors.Runtime;
12using SharpVectors.Renderers;
13using SharpVectors.Renderers.Wpf;
14using SharpVectors.Renderers.Utils;
15
16namespace SharpVectors.Converters
17{
18    /// <summary>
19    /// <para>
20    /// This converts an SVG file to the corresponding XAML file, which can
21    /// be viewed in WPF application.
22    /// </para>
23    /// <para>
24    /// The root object in the converted file is <see cref="DrawingGroup"/>.
25    /// </para>
26    /// </summary>
27    public sealed class FileSvgConverter : SvgConverter
28    {
29        #region Private Fields
30
31        private bool _writerErrorOccurred;
32        private bool _fallbackOnWriterError;
33
34        /// <summary>
35        /// Required designer variable.
36        /// </summary>
37        private WpfSvgWindow       _wpfWindow;
38        private WpfDrawingRenderer _wpfRenderer;
39
40        #endregion
41
42        #region Constructors and Destructor
43
44        /// <overloads>
45        /// Initializes a new instance of the <see cref="FileSvgConverter"/> class.
46        /// </overloads>
47        /// <summary>
48        /// Initializes a new instance of the <see cref="FileSvgConverter"/> class
49        /// with the specified drawing or rendering settings.
50        /// </summary>
51        /// <param name="settings">
52        /// This specifies the settings used by the rendering or drawing engine.
53        /// If this is <see langword="null"/>, the default settings is used.
54        /// </param>
55        public FileSvgConverter(WpfDrawingSettings settings)
56            : this(true, false, settings)
57        {
58        }
59
60        /// <summary>
61        /// Initializes a new instance of the <see cref="FileSvgConverter"/> class
62        /// with the specified drawing or rendering settings and the saving options.
63        /// </summary>
64        /// <param name="saveXaml">
65        /// This specifies whether to save result object tree in XAML file.
66        /// </param>
67        /// <param name="saveZaml">
68        /// This specifies whether to save result object tree in ZAML file. The
69        /// ZAML is simply a G-Zip compressed XAML format, similar to the SVGZ.
70        /// </param>
71        /// <param name="settings">
72        /// This specifies the settings used by the rendering or drawing engine.
73        /// If this is <see langword="null"/>, the default settings is used.
74        /// </param>
75        public FileSvgConverter(bool saveXaml, bool saveZaml,
76            WpfDrawingSettings settings)
77            : base(saveXaml, saveZaml, settings)
78        {
79            _wpfRenderer = new WpfDrawingRenderer(this.DrawingSettings);
80            _wpfWindow   = new WpfSvgWindow(640, 480, _wpfRenderer);
81        }
82
83        #endregion
84
85        #region Public Properties
86
87        /// <summary>
88        /// Gets a value indicating whether a writer error occurred when
89        /// using the custom XAML writer.
90        /// </summary>
91        /// <value>
92        /// This is <see langword="true"/> if an error occurred when using
93        /// the custom XAML writer; otherwise, it is <see langword="false"/>.
94        /// </value>
95        public bool WriterErrorOccurred
96        {
97            get
98            {
99                return _writerErrorOccurred;
100            }
101        }
102
103        /// <summary>
104        /// Gets or sets a value indicating whether to fall back and use
105        /// the .NET Framework XAML writer when an error occurred in using the
106        /// custom writer.
107        /// </summary>
108        /// <value>
109        /// This is <see langword="true"/> if the converter falls back to using
110        /// the system XAML writer when an error occurred in using the custom
111        /// writer; otherwise, it is <see langword="false"/>. If <see langword="false"/>,
112        /// an exception, which occurred in using the custom writer will be
113        /// thrown. The default is <see langword="false"/>.
114        /// </value>
115        public bool FallbackOnWriterError
116        {
117            get
118            {
119                return _fallbackOnWriterError;
120            }
121            set
122            {
123                _fallbackOnWriterError = value;
124            }
125        }
126
127        #endregion
128
129        #region Public Methods
130
131        /// <overloads>
132        /// This performs the conversion of the specified SVG file, and saves
133        /// the output to an XAML file.
134        /// </overloads>
135        /// <summary>
136        /// This performs the conversion of the specified SVG file, and saves
137        /// the output to an XAML file with the same file name.
138        /// </summary>
139        /// <param name="svgFileName">
140        /// The full path of the SVG source file.
141        /// </param>
142        /// <returns>
143        /// This returns <see langword="true"/> if the conversion is successful;
144        /// otherwise, it return <see langword="false"/>.
145        /// </returns>
146        /// <exception cref="ArgumentNullException">
147        /// If the <paramref name="svgFileName"/> is <see langword="null"/>.
148        /// </exception>
149        /// <exception cref="ArgumentException">
150        /// If the <paramref name="svgFileName"/> is empty.
151        /// <para>-or-</para>
152        /// If the <paramref name="svgFileName"/> does not exists.
153        /// </exception>
154        public bool Convert(string svgFileName)
155        {
156            return this.Convert(svgFileName, String.Empty);
157        }
158
159        /// <summary>
160        /// This performs the conversion of the specified SVG file, and saves
161        /// the output to the specified XAML file.
162        /// </summary>
163        /// <param name="svgFileName">
164        /// The full path of the SVG source file.
165        /// </param>
166        /// <param name="xamlFileName">
167        /// The output XAML file. This is optional. If not specified, an XAML
168        /// file is created in the same directory as the SVG file.
169        /// </param>
170        /// <returns>
171        /// This returns <see langword="true"/> if the conversion is successful;
172        /// otherwise, it return <see langword="false"/>.
173        /// </returns>
174        /// <exception cref="ArgumentNullException">
175        /// If the <paramref name="svgFileName"/> is <see langword="null"/>.
176        /// </exception>
177        /// <exception cref="ArgumentException">
178        /// If the <paramref name="svgFileName"/> is empty.
179        /// <para>-or-</para>
180        /// If the <paramref name="svgFileName"/> does not exists.
181        /// </exception>
182        public bool Convert(string svgFileName, string xamlFileName)
183        {
184            if (svgFileName == null)
185            {
186                throw new ArgumentNullException("svgFileName",
187                    "The SVG source file cannot be null (or Nothing).");
188            }
189            if (svgFileName.Length == 0)
190            {
191                throw new ArgumentException(
192                    "The SVG source file cannot be empty.", "svgFileName");
193            }
194            if (!File.Exists(svgFileName))
195            {
196                throw new ArgumentException(
197                    "The SVG source file must exists.", "svgFileName");
198            }
199
200            if (!this.SaveXaml && !this.SaveZaml)
201            {
202                return false;
203            }
204
205            if (!String.IsNullOrEmpty(xamlFileName))
206            {
207                string workingDir = Path.GetDirectoryName(xamlFileName);
208                if (!Directory.Exists(workingDir))
209                {
210                    Directory.CreateDirectory(workingDir);
211                }
212            }
213
214            return this.ProcessFile(svgFileName, xamlFileName);
215        }
216
217        /// <summary>
218        /// This performs the conversion of the specified SVG source, and saves
219        /// the output to the specified XAML file.
220        /// </summary>
221        /// <param name="svgStream">
222        /// A stream providing access to the SVG source data.
223        /// </param>
224        /// <param name="xamlFileName">
225        /// The output XAML file. This is optional. If not specified, an XAML
226        /// file is created in the same directory as the SVG file.
227        /// </param>
228        /// <returns>
229        /// This returns <see langword="true"/> if the conversion is successful;
230        /// otherwise, it return <see langword="false"/>.
231        /// </returns>
232        /// <exception cref="ArgumentNullException">
233        /// If the <paramref name="xamlFileName"/> is <see langword="null"/>.
234        /// <para>-or-</para>
235        /// If the <paramref name="svgStream"/> is <see langword="null"/>.
236        /// </exception>
237        /// <exception cref="ArgumentException">
238        /// If the <paramref name="xamlFileName"/> is empty.
239        /// </exception>
240        public bool Convert(Stream svgStream, string xamlFileName)
241        {
242            if (svgStream == null)
243            {
244                throw new ArgumentNullException("svgStream",
245                    "The SVG source file cannot be null (or Nothing).");
246            }
247            if (xamlFileName == null)
248            {
249                throw new ArgumentNullException("xamlFileName",
250                    "The XAML destination file path cannot be null (or Nothing).");
251            }
252            if (xamlFileName.Length == 0)
253            {
254                throw new ArgumentException(
255                    "The XAML destination file path cannot be empty.", "xamlFileName");
256            }
257
258            if (!this.SaveXaml && !this.SaveZaml)
259            {
260                return false;
261            }
262
263            if (!String.IsNullOrEmpty(xamlFileName))
264            {
265                string workingDir = Path.GetDirectoryName(xamlFileName);
266                if (!Directory.Exists(workingDir))
267                {
268                    Directory.CreateDirectory(workingDir);
269                }
270            }
271
272            return this.ProcessFile(svgStream, xamlFileName);
273        }
274
275        /// <summary>
276        /// This performs the conversion of the specified SVG source, and saves
277        /// the output to the specified XAML file.
278        /// </summary>
279        /// <param name="svgTextReader">
280        /// A text reader providing access to the SVG source data.
281        /// </param>
282        /// <param name="xamlFileName">
283        /// The output XAML file. This is optional. If not specified, an XAML
284        /// file is created in the same directory as the SVG file.
285        /// </param>
286        /// <returns>
287        /// This returns <see langword="true"/> if the conversion is successful;
288        /// otherwise, it return <see langword="false"/>.
289        /// </returns>
290        /// <exception cref="ArgumentNullException">
291        /// If the <paramref name="xamlFileName"/> is <see langword="null"/>.
292        /// <para>-or-</para>
293        /// If the <paramref name="svgTextReader"/> is <see langword="null"/>.
294        /// </exception>
295        /// <exception cref="ArgumentException">
296        /// If the <paramref name="xamlFileName"/> is empty.
297        /// </exception>
298        public bool Convert(TextReader svgTextReader, string xamlFileName)
299        {
300            if (svgTextReader == null)
301            {
302                throw new ArgumentNullException("svgTextReader",
303                    "The SVG source file cannot be null (or Nothing).");
304            }
305            if (xamlFileName == null)
306            {
307                throw new ArgumentNullException("xamlFileName",
308                    "The XAML destination file path cannot be null (or Nothing).");
309            }
310            if (xamlFileName.Length == 0)
311            {
312                throw new ArgumentException(
313                    "The XAML destination file path cannot be empty.", "xamlFileName");
314            }
315
316            if (!this.SaveXaml && !this.SaveZaml)
317            {
318                return false;
319            }
320
321            if (!String.IsNullOrEmpty(xamlFileName))
322            {
323                string workingDir = Path.GetDirectoryName(xamlFileName);
324                if (!Directory.Exists(workingDir))
325                {
326                    Directory.CreateDirectory(workingDir);
327                }
328            }
329
330            return this.ProcessFile(svgTextReader, xamlFileName);
331        }
332
333        /// <summary>
334        /// This performs the conversion of the specified SVG source, and saves
335        /// the output to the specified XAML file.
336        /// </summary>
337        /// <param name="svgXmlReader">
338        /// An XML reader providing access to the SVG source data.
339        /// </param>
340        /// <param name="xamlFileName">
341        /// The output XAML file. This is optional. If not specified, an XAML
342        /// file is created in the same directory as the SVG file.
343        /// </param>
344        /// <returns>
345        /// This returns <see langword="true"/> if the conversion is successful;
346        /// otherwise, it return <see langword="false"/>.
347        /// </returns>
348        /// <exception cref="ArgumentNullException">
349        /// If the <paramref name="xamlFileName"/> is <see langword="null"/>.
350        /// <para>-or-</para>
351        /// If the <paramref name="svgXmlReader"/> is <see langword="null"/>.
352        /// </exception>
353        /// <exception cref="ArgumentException">
354        /// If the <paramref name="xamlFileName"/> is empty.
355        /// </exception>
356        public bool Convert(XmlReader svgXmlReader, string xamlFileName)
357        {
358            if (svgXmlReader == null)
359            {
360                throw new ArgumentNullException("svgXmlReader",
361                    "The SVG source file cannot be null (or Nothing).");
362            }
363            if (xamlFileName == null)
364            {
365                throw new ArgumentNullException("xamlFileName",
366                    "The XAML destination file path cannot be null (or Nothing).");
367            }
368            if (xamlFileName.Length == 0)
369            {
370                throw new ArgumentException(
371                    "The XAML destination file path cannot be empty.", "xamlFileName");
372            }
373
374            if (!this.SaveXaml && !this.SaveZaml)
375            {
376                return false;
377            }
378
379            if (!String.IsNullOrEmpty(xamlFileName))
380            {
381                string workingDir = Path.GetDirectoryName(xamlFileName);
382                if (!Directory.Exists(workingDir))
383                {
384                    Directory.CreateDirectory(workingDir);
385                }
386            }
387
388            return this.ProcessFile(svgXmlReader, xamlFileName);
389        }
390
391        #endregion
392
393        #region Private Methods
394
395        #region ProcessFile Method
396
397        private bool ProcessFile(string fileName, string xamlFileName)
398        {
399            _wpfRenderer.LinkVisitor       = new LinkVisitor();
400            _wpfRenderer.ImageVisitor      = new EmbeddedImageVisitor();
401            _wpfRenderer.FontFamilyVisitor = new FontFamilyVisitor();
402
403            _wpfWindow.LoadDocument(fileName);
404
405            _wpfRenderer.InvalidRect = SvgRectF.Empty;
406
407            _wpfRenderer.Render(_wpfWindow.Document as SvgDocument);
408
409            DrawingGroup renderedDrawing = _wpfRenderer.Drawing as DrawingGroup;
410            if (renderedDrawing == null)
411            {
412                return false;
413            }
414
415            SaveFile(renderedDrawing, fileName, xamlFileName);
416
417            renderedDrawing = null;
418
419            return true;
420        }
421
422        private bool ProcessFile(Stream svgStream, string xamlFileName)
423        {
424            _wpfRenderer.LinkVisitor       = new LinkVisitor();
425            _wpfRenderer.ImageVisitor      = new EmbeddedImageVisitor();
426            _wpfRenderer.FontFamilyVisitor = new FontFamilyVisitor();
427
428            _wpfWindow.LoadDocument(svgStream);
429
430            _wpfRenderer.InvalidRect = SvgRectF.Empty;
431
432            _wpfRenderer.Render(_wpfWindow.Document as SvgDocument);
433
434            DrawingGroup renderedDrawing = _wpfRenderer.Drawing as DrawingGroup;
435            if (renderedDrawing == null)
436            {
437                return false;
438            }
439
440            SaveFile(renderedDrawing, xamlFileName, xamlFileName);
441
442            renderedDrawing = null;
443
444            return true;
445        }
446
447        private bool ProcessFile(TextReader svgTextReader, string xamlFileName)
448        {
449            _wpfRenderer.LinkVisitor       = new LinkVisitor();
450            _wpfRenderer.ImageVisitor      = new EmbeddedImageVisitor();
451            _wpfRenderer.FontFamilyVisitor = new FontFamilyVisitor();
452
453            _wpfWindow.LoadDocument(svgTextReader);
454
455            _wpfRenderer.InvalidRect = SvgRectF.Empty;
456
457            _wpfRenderer.Render(_wpfWindow.Document as SvgDocument);
458
459            DrawingGroup renderedDrawing = _wpfRenderer.Drawing as DrawingGroup;
460            if (renderedDrawing == null)
461            {
462                return false;
463            }
464
465            SaveFile(renderedDrawing, xamlFileName, xamlFileName);
466
467            renderedDrawing = null;
468
469            return true;
470        }
471
472        private bool ProcessFile(XmlReader svgXmlReader, string xamlFileName)
473        {
474            _wpfRenderer.LinkVisitor       = new LinkVisitor();
475            _wpfRenderer.ImageVisitor      = new EmbeddedImageVisitor();
476            _wpfRenderer.FontFamilyVisitor = new FontFamilyVisitor();
477
478            _wpfWindow.LoadDocument(svgXmlReader);
479
480            _wpfRenderer.InvalidRect = SvgRectF.Empty;
481
482            _wpfRenderer.Render(_wpfWindow.Document as SvgDocument);
483
484            DrawingGroup renderedDrawing = _wpfRenderer.Drawing as DrawingGroup;
485            if (renderedDrawing == null)
486            {
487                return false;
488            }
489
490            SaveFile(renderedDrawing, xamlFileName, xamlFileName);
491
492            renderedDrawing = null;
493
494            return true;
495        }
496
497        #endregion
498
499        #region SaveFile Method
500
501        private bool SaveFile(Drawing drawing, string fileName, string xamlFileName)
502        {
503            _writerErrorOccurred = false;
504
505            if (String.IsNullOrEmpty(xamlFileName))
506            {
507                string fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileName);
508
509                string workingDir  = Path.GetDirectoryName(fileName);
510                xamlFileName       = Path.Combine(workingDir,
511                    fileNameWithoutExt + ".xaml");
512            }
513            else
514            {
515                string fileExt = Path.GetExtension(xamlFileName);
516                if (String.IsNullOrEmpty(fileExt))
517                {
518                    xamlFileName += ".xaml";
519                }
520                else if (!String.Equals(fileExt, ".xaml",
521                    StringComparison.OrdinalIgnoreCase))
522                {
523                    xamlFileName = Path.ChangeExtension(xamlFileName, ".xaml");
524                }
525            }
526
527            if (File.Exists(xamlFileName))
528            {
529                File.SetAttributes(xamlFileName, FileAttributes.Normal);
530                File.Delete(xamlFileName);
531            }
532
533            if (this.UseFrameXamlWriter)
534            {
535                XmlWriterSettings writerSettings = new XmlWriterSettings();
536                writerSettings.Indent = true;
537                writerSettings.OmitXmlDeclaration = true;
538                writerSettings.Encoding = Encoding.UTF8;
539                using (FileStream xamlFile = File.Create(xamlFileName))
540                {
541                    using (XmlWriter writer = XmlWriter.Create(
542                        xamlFile, writerSettings))
543                    {
544                        System.Windows.Markup.XamlWriter.Save(
545                            drawing, writer);
546                    }
547                }
548            }
549            else
550            {
551                try
552                {
553                    XmlXamlWriter xamlWriter = new XmlXamlWriter(
554                        this.DrawingSettings);
555
556                    using (FileStream xamlFile = File.Create(xamlFileName))
557                    {
558                        xamlWriter.Save(drawing, xamlFile);
559                    }
560                }
561                catch
562                {
563                    _writerErrorOccurred = true;
564
565                    if (_fallbackOnWriterError)
566                    {
567                        if (File.Exists(xamlFileName))
568                        {
569                            File.Move(xamlFileName, xamlFileName + ".bak");
570                        }
571
572                        XmlWriterSettings writerSettings = new XmlWriterSettings();
573                        writerSettings.Indent = true;
574                        writerSettings.OmitXmlDeclaration = true;
575                        writerSettings.Encoding = Encoding.UTF8;
576                        using (FileStream xamlFile = File.Create(xamlFileName))
577                        {
578                            using (XmlWriter writer = XmlWriter.Create(
579                                xamlFile, writerSettings))
580                            {
581                                System.Windows.Markup.XamlWriter.Save(
582                                    drawing, writer);
583                            }
584                        }
585                    }
586                    else
587                    {
588                        throw;
589                    }
590                }
591            }
592
593            if (this.SaveZaml)
594            {
595                string zamlFileName = Path.ChangeExtension(xamlFileName, ".zaml");
596
597                if (File.Exists(zamlFileName))
598                {
599                    File.SetAttributes(zamlFileName, FileAttributes.Normal);
600                    File.Delete(zamlFileName);
601                }
602
603                FileStream zamlSourceFile = new FileStream(xamlFileName, FileMode.Open,
604                    FileAccess.Read, FileShare.Read);
605                byte[] buffer = new byte[zamlSourceFile.Length];
606                // Read the file to ensure it is readable.
607                int count = zamlSourceFile.Read(buffer, 0, buffer.Length);
608                if (count != buffer.Length)
609                {
610                    zamlSourceFile.Close();
611                    return false;
612                }
613                zamlSourceFile.Close();
614
615                FileStream zamlDestFile = File.Create(zamlFileName);
616
617                GZipStream zipStream = new GZipStream(zamlDestFile, CompressionMode.Compress, true);
618                zipStream.Write(buffer, 0, buffer.Length);
619
620                zipStream.Close();
621
622                zamlDestFile.Close();
623            }
624
625            if (!this.SaveXaml && File.Exists(xamlFileName))
626            {
627                File.Delete(xamlFileName);
628            }
629
630            return true;
631        }
632
633        #endregion
634
635        #endregion
636    }
637}
Note: See TracBrowser for help on using the repository browser.