SvgDocument.cs 8.9 KB
Newer Older
davescriven's avatar
davescriven committed
1
2
3
4
5
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
6
7
using System.Drawing.Drawing2D;
using System.Drawing.Text;
davescriven's avatar
davescriven committed
8
9
10
11
12
13
14
15
16
17
18
19
using System.IO;
using System.Text;
using System.Xml;

namespace Svg
{
    /// <summary>
    /// The class used to create and load all SVG documents.
    /// </summary>
    public class SvgDocument : SvgFragment, ITypeDescriptorContext
    {
        public static readonly int PPI = 96;
20

davescriven's avatar
davescriven committed
21
22
23
24
25
        /// <summary>
        /// Gets a <see cref="string"/> containing the XLink namespace (http://www.w3.org/1999/xlink).
        /// </summary>
        public static readonly string XLinkNamespace = "http://www.w3.org/1999/xlink";

26
27
28
        private SvgElementIdManager _idManager;

        public SvgDocument()
davescriven's avatar
davescriven committed
29
        {
30
            Ppi = 96;
davescriven's avatar
davescriven committed
31
32
33
34
35
36
37
38
39
        }

        /// <summary>
        /// Gets an <see cref="SvgElementIdManager"/> for this document.
        /// </summary>
        protected internal virtual SvgElementIdManager IdManager
        {
            get
            {
40
41
                if (_idManager == null)
                    _idManager = new SvgElementIdManager(this);
davescriven's avatar
davescriven committed
42

43
                return _idManager;
davescriven's avatar
davescriven committed
44
45
46
            }
        }

47
48
49
50
51
        public int Ppi { get; set; }

        #region ITypeDescriptorContext Members

        IContainer ITypeDescriptorContext.Container
davescriven's avatar
davescriven committed
52
        {
53
            get { throw new NotImplementedException(); }
davescriven's avatar
davescriven committed
54
55
        }

56
        object ITypeDescriptorContext.Instance
davescriven's avatar
davescriven committed
57
        {
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
            get { return this; }
        }

        void ITypeDescriptorContext.OnComponentChanged()
        {
            throw new NotImplementedException();
        }

        bool ITypeDescriptorContext.OnComponentChanging()
        {
            throw new NotImplementedException();
        }

        PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
        {
            get { throw new NotImplementedException(); }
        }

        object IServiceProvider.GetService(Type serviceType)
        {
            throw new NotImplementedException();
        }

        #endregion

        /// <summary>
        /// Retrieves the <see cref="SvgElement"/> with the specified ID.
        /// </summary>
        /// <param name="id">A <see cref="string"/> containing the ID of the element to find.</param>
        /// <returns>An <see cref="SvgElement"/> of one exists with the specified ID; otherwise false.</returns>
        public virtual SvgElement GetElementById(string id)
        {
            return IdManager.GetElementById(id);
davescriven's avatar
davescriven committed
91
92
93
94
95
96
97
98
99
        }

        /// <summary>
        /// Opens the document at the specified path and loads the contents.
        /// </summary>
        /// <param name="path">A <see cref="string"/> containing the path of the file to open.</param>
        /// <returns>An <see cref="SvgDocument"/> with the contents loaded.</returns>
        /// <exception cref="FileNotFoundException">The document at the specified <paramref name="path"/> cannot be found.</exception>
        public static SvgDocument Open(string path)
100
101
102
103
104
        {
            return Open(path, null);
        }

        public static SvgDocument Open(string path, Dictionary<string, string> entities)
davescriven's avatar
davescriven committed
105
106
107
108
        {
            if (!File.Exists(path))
                throw new FileNotFoundException("The specified document cannot be found.", path);

109
            return Open(File.OpenRead(path), entities);
davescriven's avatar
davescriven committed
110
111
112
113
114
115
116
117
118
119
120
121
        }

        public static SvgDocument Open(Stream stream)
        {
            return Open(stream, null);
        }

        public static SvgDocument OpenRender(Stream stream, Graphics graphics)
        {
            return null;
        }

122
        public static SvgDocument Open(Stream stream, Dictionary<string, string> entities)
davescriven's avatar
davescriven committed
123
124
125
        {
            Trace.TraceInformation("Begin Read");

126
            using (var reader = new SvgTextReader(stream, entities))
davescriven's avatar
davescriven committed
127
            {
128
129
                var elementStack = new Stack<SvgElement>();
                var value = new StringBuilder();
davescriven's avatar
davescriven committed
130
                SvgElement element = null;
131
                SvgElement parent;
davescriven's avatar
davescriven committed
132
133
134
135
136
137
138
139
140
141
142
143
144
                SvgDocument svgDocument = null;
                reader.XmlResolver = new SvgDtdResolver();
                reader.WhitespaceHandling = WhitespaceHandling.None;

                while (reader.Read())
                {
                    try
                    {
                        switch (reader.NodeType)
                        {
                            case XmlNodeType.Element:
                                // Does this element have a value or children
                                // (Must do this check here before we progress to another node)
145
                                bool isEmpty = reader.IsEmptyElement;
davescriven's avatar
davescriven committed
146
147
148
149
150
151
                                // Create element
                                if (elementStack.Count > 0)
                                    element = SvgElementFactory.CreateElement(reader, svgDocument);
                                else
                                {
                                    element = SvgElementFactory.CreateDocument(reader);
152
                                    svgDocument = (SvgDocument) element;
davescriven's avatar
davescriven committed
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
                                }

                                if (element == null)
                                    continue;

                                // Add to the parents children
                                if (elementStack.Count > 0)
                                {
                                    parent = elementStack.Peek();
                                    parent.Children.Add(element);
                                }

                                // Push element into stack
                                elementStack.Push(element);

                                // Need to process if the element is empty
                                if (isEmpty)
                                    goto case XmlNodeType.EndElement;

                                break;
                            case XmlNodeType.EndElement:
                                // Skip if no element was created
                                if (element == null)
                                    continue;
                                // Pop the element out of the stack
                                element = elementStack.Pop();

                                if (value.Length > 0)
                                {
                                    element.Content = value.ToString();
                                    // Reset content value for new element
                                    value = new StringBuilder();
                                }
                                break;
                            case XmlNodeType.CDATA:
                            case XmlNodeType.Text:
                                value.Append(reader.Value);
                                break;
                        }
                    }
                    catch (Exception exc)
                    {
                        Trace.TraceError(exc.Message);
                    }
                }

                Trace.TraceInformation("End Read");
                return svgDocument;
            }
        }

204
        public static SvgDocument Open(XmlDocument document)
davescriven's avatar
davescriven committed
205
206
207
208
209
210
211
212
213
        {
            return null;
        }

        public static Bitmap OpenAsBitmap(string path)
        {
            return null;
        }

214
        public static Bitmap OpenAsBitmap(XmlDocument document)
davescriven's avatar
davescriven committed
215
216
217
218
219
220
        {
            return null;
        }

        public RectangleF GetDimensions()
        {
221
            return new RectangleF(0, 0, Width.ToDeviceValue(), Height.ToDeviceValue());
davescriven's avatar
davescriven committed
222
223
224
225
        }

        public void Draw(Graphics graphics)
        {
226
            Render(graphics);
davescriven's avatar
davescriven committed
227
228
229
230
231
232
        }

        public virtual Bitmap Draw()
        {
            Trace.TraceInformation("Begin Render");

233
234
235
            var size = GetDimensions();

            var bitmap = new Bitmap((int) Math.Ceiling(size.Width), (int) Math.Ceiling(size.Height));
davescriven's avatar
davescriven committed
236

237
            try
davescriven's avatar
davescriven committed
238
            {
239
240
241
242
243
244
245
246
247
248
249
250
251
                using (var g = Graphics.FromImage(bitmap))
                {
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;
                    g.TextContrast = 1;
                    g.PixelOffsetMode = PixelOffsetMode.Half;
                    Render(g);
                    g.Save();
                }
            }
            catch
            {
                bitmap.Dispose();
                throw;
davescriven's avatar
davescriven committed
252
253
254
255
256
257
258
259
            }

            Trace.TraceInformation("End Render");
            return bitmap;
        }

        public void Write(Stream stream)
        {
260
            using (new XmlTextWriter(stream, Encoding.UTF8))
davescriven's avatar
davescriven committed
261
262
263
264
265
266
            {
            }
        }

        public void Write(string path)
        {
267
            Write(File.Create(path));
davescriven's avatar
davescriven committed
268
269
270
        }
    }
}