Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorConverters/FileSvgReader.cs @ 13398

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

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

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