SvgPatternServer.cs 4.73 KB
Newer Older
davescriven's avatar
davescriven committed
1
2
3
4
5
6
7
8
9
10
11
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.ComponentModel;

using Svg.Transforms;

namespace Svg
{
12
13
14
15
    /// <summary>
    /// A pattern is used to fill or stroke an object using a pre-defined graphic object which can be replicated ("tiled") at fixed intervals in x and y to cover the areas to be painted.
    /// </summary>
    [SvgElement("pattern")]
davescriven's avatar
davescriven committed
16
17
18
19
20
21
22
23
    public sealed class SvgPatternServer : SvgPaintServer, ISvgViewPort
    {
        private SvgUnit _width;
        private SvgUnit _height;
        private SvgUnit _x;
        private SvgUnit _y;
        private SvgViewBox _viewBox;

24
25
26
27
        /// <summary>
        /// Specifies a supplemental transformation which is applied on top of any 
        /// transformations necessary to create a new pattern coordinate system.
        /// </summary>
davescriven's avatar
davescriven committed
28
29
30
31
32
33
34
        [SvgAttribute("viewBox")]
        public SvgViewBox ViewBox
        {
            get { return this._viewBox; }
            set { this._viewBox = value; }
        }

35
36
37
        /// <summary>
        /// Gets or sets the width of the pattern.
        /// </summary>
davescriven's avatar
davescriven committed
38
39
40
41
42
43
44
        [SvgAttribute("width")]
        public SvgUnit Width
        {
            get { return this._width; }
            set { this._width = value; }
        }

45
46
47
        /// <summary>
        /// Gets or sets the height of the pattern.
        /// </summary>
davescriven's avatar
davescriven committed
48
49
50
51
52
53
54
        [SvgAttribute("height")]
        public SvgUnit Height
        {
            get { return this._height; }
            set { this._height = value; }
        }

55
56
57
        /// <summary>
        /// Gets or sets the X-axis location of the pattern.
        /// </summary>
davescriven's avatar
davescriven committed
58
59
60
61
62
63
64
        [SvgAttribute("x")]
        public SvgUnit X
        {
            get { return this._x; }
            set { this._x = value; }
        }

65
66
67
        /// <summary>
        /// Gets or sets the Y-axis location of the pattern.
        /// </summary>
davescriven's avatar
davescriven committed
68
69
70
71
72
73
74
        [SvgAttribute("y")]
        public SvgUnit Y
        {
            get { return this._y; }
            set { this._y = value; }
        }

75
76
77
        /// <summary>
        /// Initializes a new instance of the <see cref="SvgPatternServer"/> class.
        /// </summary>
davescriven's avatar
davescriven committed
78
79
80
81
82
83
84
85
        public SvgPatternServer()
        {
            this._x = new SvgUnit(0.0f);
            this._y = new SvgUnit(0.0f);
            this._width = new SvgUnit(0.0f);
            this._height = new SvgUnit(0.0f);
        }

86
87
88
89
90
        /// <summary>
        /// Gets a <see cref="Brush"/> representing the current paint server.
        /// </summary>
        /// <param name="styleOwner">The owner <see cref="SvgVisualElement"/>.</param>
        /// <param name="opacity">The opacity of the brush.</param>
91
        public override Brush GetBrush(SvgVisualElement renderingElement, float opacity)
davescriven's avatar
davescriven committed
92
93
94
95
96
97
98
99
100
101
102
103
104
        {
            // If there aren't any children, return null
            if (this.Children.Count == 0)
                return null;

            // Can't render if there are no dimensions
            if (this._width.Value == 0.0f || this._height.Value == 0.0f)
                return null;

            float width = this._width.ToDeviceValue(renderingElement);
            float height = this._height.ToDeviceValue(renderingElement, true);

            Bitmap image = new Bitmap((int)width, (int)height);
105
            using (SvgRenderer renderer = SvgRenderer.FromImage(image))
davescriven's avatar
davescriven committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
            {
                Matrix patternMatrix = new Matrix();

                // Apply a translate if needed
                if (this._x.Value > 0.0f || this._y.Value > 0.0f)
                {
                    patternMatrix.Translate(this._x.ToDeviceValue(renderingElement) + -1.0f, this._y.ToDeviceValue(renderingElement, true) + -1.0f);
                }
                else
                {
                    patternMatrix.Translate(-1, -1);
                }

                if (this.ViewBox.Height > 0 || this.ViewBox.Width > 0)
                {
                    patternMatrix.Scale(this.Width.ToDeviceValue() / this.ViewBox.Width, this.Height.ToDeviceValue() / this.ViewBox.Height);
                }

124
125
126
127
                renderer.Transform = patternMatrix;
                renderer.CompositingQuality = CompositingQuality.HighQuality;
                renderer.SmoothingMode = SmoothingMode.AntiAlias;
                renderer.PixelOffsetMode = PixelOffsetMode.Half;
davescriven's avatar
davescriven committed
128
129
130

                foreach (SvgElement child in this.Children)
                {
131
                    child.RenderElement(renderer);
davescriven's avatar
davescriven committed
132
133
                }

134
                renderer.Save();
davescriven's avatar
davescriven committed
135
136
137
138
139
140
141
142
            }

            TextureBrush textureBrush = new TextureBrush(image);

            return textureBrush;
        }
    }
}