Click here to Skip to main content
15,891,033 members
Articles / Desktop Programming / WPF

SharpVectors - SVG# Reloaded: An Introduction

Rate me:
Please Sign up or sign in to vote.
4.98/5 (33 votes)
17 Nov 2010BSD10 min read 205.3K   21.7K   101  
A C# library for converting SVG to WPF and viewing SVG files in WPF Applications
using System;
using System.Globalization;

namespace SharpVectors.Dom.Svg
{
    /// <summary>
    /// This stores a set of four float precision numbers that represent the 
    /// location and size of a rectangle.
    /// </summary>
    [Serializable]
    public struct SvgRectF : IEquatable<SvgRectF>
    {
        #region Private Fields

        /// <summary>
        /// Represents an instance of the <see cref="SvgRectF"/> structure 
        /// with its members uninitialized.
        /// </summary>
        public static readonly SvgRectF Empty = new SvgRectF();
                    
        private float _x;
        private float _y;
        private float _width;
        private float _height;

        #endregion

        #region Constructors and Destructor

        /// <summary>
        /// Initializes a new instance of the <see cref="SvgRectF"/> 
        /// structure with the specified location and size.
        /// </summary>
        /// <param name="x">
        /// The x-coordinate of the upper-left corner of the rectangle. 
        /// </param>
        /// <param name="y">
        /// The y-coordinate of the upper-left corner of the rectangle. 
        /// </param>
        /// <param name="width">The width of the rectangle. </param>
        /// <param name="height">The height of the rectangle. </param>
        public SvgRectF(float x, float y, float width, float height)
        {
            _x      = x;
            _y      = y;
            _width  = width;
            _height = height;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SvgRectF"/> structure 
        /// with the specified location and size.
        /// </summary>
        /// <param name="size">
        /// A <see cref="SvgSizeF"/> that represents the width and height of the 
        /// rectangular region.
        /// </param>
        /// <param name="location">
        /// A <see cref="SvgPointF"/> that represents the upper-left corner 
        /// of the rectangular region. 
        /// </param>
        public SvgRectF(SvgPointF location, SvgSizeF size)
        {
            _x      = location.X;
            _y      = location.Y;
            _width  = size.Width;
            _height = size.Height;
        }

        /// <summary>
        /// Creates a <see cref="SvgRectF"/> structure with upper-left corner 
        /// and lower-right corner at the specified locations.
        /// </summary>
        /// <param name="left">
        /// The x-coordinate of the upper-left corner of the rectangular region. 
        /// </param>
        /// <param name="top">
        /// The y-coordinate of the upper-left corner of the rectangular region.
        /// </param>
        /// <param name="right">
        /// The x-coordinate of the lower-right corner of the rectangular region. 
        /// </param>
        /// <param name="bottom">
        /// The y-coordinate of the lower-right corner of the rectangular region.
        /// </param>
        /// <returns>
        /// The new <see cref="SvgRectF"/> that this method creates.
        /// </returns>
        public static SvgRectF Create(float left, float top, 
            float right, float bottom)
        {
            return new SvgRectF(left, top, right - left, bottom - top);
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the coordinates of the upper-left corner of this 
        /// <see cref="SvgRectF"/> structure.
        /// </summary>
        /// <value>
        /// A <see cref="SvgPointF"/> that represents the upper-left corner of this 
        /// <see cref="SvgRectF"/> structure.
        /// </value>
        public SvgPointF Location
        {
            get
            {
                return new SvgPointF(_x, _y);
            }
            set
            {
                _x = value.X;
                _y = value.Y;
            }
        }

        /// <summary>
        /// Gets or sets the size of this <see cref="SvgRectF"/>.
        /// </summary>
        /// <value>
        /// A <see cref="SvgSizeF"/> that represents the width and height of this 
        /// <see cref="SvgRectF"/> structure.
        /// </value>
        public SvgSizeF Size
        {
            get
            {
                return new SvgSizeF(_width, _height);
            }
            set
            {
                _width  = value.Width;
                _height = value.Height;
            }
        }

        /// <summary>
        /// Gets or sets the x-coordinate of the upper-left corner of this 
        /// <see cref="SvgRectF"/> structure.
        /// </summary>
        /// <value>
        /// The x-coordinate of the upper-left corner of this 
        /// <see cref="SvgRectF"/> structure.
        /// </value>
        public float X
        {
            get
            {
                return _x;
            }
            set
            {
                _x = value;
            }
        }

        /// <summary>
        /// Gets or sets the y-coordinate of the upper-left corner of this 
        /// <see cref="SvgRectF"/> structure.
        /// </summary>
        /// <value>
        /// The y-coordinate of the upper-left corner of this 
        /// <see cref="SvgRectF"/> structure. 
        /// </value>
        public float Y
        {
            get
            {
                return _y;
            }
            set
            {
                _y = value;
            }
        }

        /// <summary>
        /// Gets or sets the width of this <see cref="SvgRectF"/> structure.
        /// </summary>
        /// <value>
        /// The width of this <see cref="SvgRectF"/> structure.
        /// </value>
        public float Width
        {
            get
            {
                return _width;
            }
            set
            {
                _width = value;
            }
        }

        /// <summary>
        /// Gets or sets the height of this <see cref="SvgRectF"/> structure.
        /// </summary>
        /// <value>
        /// The height of this <see cref="SvgRectF"/> structure.
        /// </value>
        public float Height
        {
            get
            {
                return _height;
            }
            set
            {
                _height = value;
            }
        }

        /// <summary>
        /// Gets the x-coordinate of the left edge of this <see cref="SvgRectF"/> 
        /// structure.
        /// </summary>
        /// <value>
        /// The x-coordinate of the left edge of this <see cref="SvgRectF"/> 
        /// structure.
        /// </value>
        public float Left
        {
            get
            {
                return _x;
            }
        }

        /// <summary>
        /// Gets the y-coordinate of the top edge of this <see cref="SvgRectF"/> 
        /// structure.
        /// </summary>
        /// <value>
        /// The y-coordinate of the top edge of this <see cref="SvgRectF"/> 
        /// structure.
        /// </value>
        public float Top
        {
            get
            {
                return _y;
            }
        }

        /// <summary>
        /// Gets the x-coordinate that is the sum of <see cref="SvgRectF.X"/> 
        /// and <see cref="SvgRectF.Width"/> of this <see cref="SvgRectF"/> 
        /// structure.
        /// </summary>
        /// <value>
        /// The x-coordinate that is the sum of <see cref="SvgRectF.X"/> and 
        /// <see cref="SvgRectF.Width"/> of this <see cref="SvgRectF"/> 
        /// structure.
        /// </value>
        public float Right
        {
            get
            {
                return (_x + _width);
            }
        }

        /// <summary>
        /// Gets the y-coordinate that is the sum of <see cref="SvgRectF.Y"/> 
        /// and <see cref="SvgRectF.Height"/> of this <see cref="SvgRectF"/> 
        /// structure.
        /// </summary>
        /// <value>
        /// The y-coordinate that is the sum of <see cref="SvgRectF.Y"/> and 
        /// <see cref="SvgRectF.Height"/> of this <see cref="SvgRectF"/> 
        /// structure.
        /// </value>
        public float Bottom
        {
            get
            {
                return (_y + _height);
            }
        }

        /// <summary>
        /// Tests whether the <see cref="SvgRectF.Width"/> or 
        /// <see cref="SvgRectF.Height"/> property of this 
        /// <see cref="SvgRectF"/> has a value of zero.
        /// </summary>
        /// <value>
        /// This property returns true if the <see cref="SvgRectF.Width"/> or 
        /// <see cref="SvgRectF.Height"/> property of this 
        /// <see cref="SvgRectF"/> has a value of zero; otherwise, false.
        /// </value>
        public bool IsEmpty
        {
            get
            {
                if (_width > 0f)
                {
                    return (_height <= 0f);
                }

                return true;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// This tests whether an object is a <see cref="SvgRectF"/> with the 
        /// same location and size of this <see cref="SvgRectF"/>.
        /// </summary>
        /// <param name="obj">
        /// The <see cref="System.Object"/> to test. 
        /// </param>
        /// <returns>
        /// This returns <see langword="true"/> if the specified object is a 
        /// <see cref="SvgRectF"/> and its <see cref="X"/>, <see cref="Y"/>, 
        /// <see cref="Width"/>, and <see cref="Height"/> properties are equal 
        /// to the corresponding properties of this <see cref="SvgRectF"/>; 
        /// otherwise, <see langword="false"/>.
        /// </returns>
        public override bool Equals(object obj)
        {
            if (obj is SvgRectF)
            {
                return Equals((SvgRectF)obj);
            }

            return false;
        }

        /// <summary>
        /// This tests whether the specified <see cref="SvgRectF"/> is with 
        /// the same location and size of this <see cref="SvgRectF"/>.
        /// </summary>
        /// <param name="other">
        /// The <see cref="SvgRectF"/> to test. 
        /// </param>
        /// <returns>
        /// This returns <see langword="true"/> if specified <see cref="SvgRectF"/> 
        /// has its <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and 
        /// <see cref="Height"/> properties are equal to the corresponding 
        /// properties of this <see cref="SvgRectF"/>; otherwise, 
        /// <see langword="false"/>.
        /// </returns>
        public bool Equals(SvgRectF other)
        {
            if (((other.X == _x) && (other.Y == _y)) && (other.Width == _width))
            {
                return (other.Height == _height);
            }

            return false;
        }

        /// <overloads>
        /// This determines if the specified point or rectangle is contained 
        /// within this <see cref="SvgRectF"/> structure.
        /// </overloads>
        /// <summary>
        /// This determines if the specified point is contained within this 
        /// <see cref="SvgRectF"/> structure.
        /// </summary>
        /// <param name="x">The x-coordinate of the point to test. </param>
        /// <param name="y">The y-coordinate of the point to test. </param>
        /// <returns>
        /// This method returns true if the point defined by x and y is 
        /// contained within this <see cref="SvgRectF"/> structure; otherwise 
        /// false.
        /// </returns>
        public bool Contains(float x, float y)
        {
            if (((_x <= x) && (x < (_x + _width))) && (_y <= y))
            {
                return (y < (_y + _height));
            }

            return false;
        }

        /// <summary>
        /// This determines if the specified point is contained within this 
        /// <see cref="SvgRectF"/> structure.
        /// </summary>
        /// <param name="pt">The <see cref="SvgPointF"/> to test. </param>
        /// <returns>
        /// This method returns true if the point represented by the pt 
        /// parameter is contained within this <see cref="SvgRectF"/> 
        /// structure; otherwise false.
        /// </returns>
        public bool Contains(SvgPointF pt)
        {
            return this.Contains(pt.X, pt.Y);
        }

        /// <summary>
        /// This determines if the rectangular region represented by rect is 
        /// entirely contained within this <see cref="SvgRectF"/> structure.
        /// </summary>
        /// <param name="rect">The <see cref="SvgRectF"/> to test. </param>
        /// <returns>
        /// This method returns true if the rectangular region represented by 
        /// rect is entirely contained within the rectangular region represented 
        /// by this <see cref="SvgRectF"/>; otherwise false.
        /// </returns>
        public bool Contains(SvgRectF rect)
        {
            if (((_x <= rect.X) && ((rect.X + rect.Width) <= 
                (_x + _width))) && (_y <= rect.Y))
            {
                return ((rect.Y + rect.Height) <= (_y + _height));
            }

            return false;
        }

        /// <summary>
        /// Gets the hash code for this <see cref="SvgRectF"/> structure. 
        /// For information about the use of hash codes, see Object.GetHashCode.
        /// </summary>
        /// <returns>The hash code for this <see cref="SvgRectF"/>.</returns>
        public override int GetHashCode()
        {
            return (_x.GetHashCode() ^ _y.GetHashCode() ^
                _width.GetHashCode() ^ _height.GetHashCode());
        }

        /// <overloads>
        /// Inflates this <see cref="SvgRectF"/> structure by the specified 
        /// amount.
        /// </overloads>
        /// <summary>
        /// Inflates this <see cref="SvgRectF"/> structure by the specified 
        /// amount.
        /// </summary>
        /// <param name="x">The amount to inflate this <see cref="SvgRectF"/> structure horizontally. </param>
        /// <param name="y">The amount to inflate this <see cref="SvgRectF"/> structure vertically. </param>
        /// <returns>This method does not return a value.</returns>
        public void Inflate(float x, float y)
        {
            _x      -= x;
            _y      -= y;
            _width  += 2f * x;
            _height += 2f * y;
        }

        /// <summary>
        /// Inflates this <see cref="SvgRectF"/> by the specified amount.
        /// </summary>
        /// <param name="size">The amount to inflate this rectangle. </param>
        /// <returns>This method does not return a value.</returns>
        public void Inflate(SvgSizeF size)
        {
            this.Inflate(size.Width, size.Height);
        }

        public void Intersect(SvgRectF rect)
        {
            SvgRectF ef = Intersection(rect, this);
            _x      = ef.X;
            _y      = ef.Y;
            _width  = ef.Width;
            _height = ef.Height;
        }

        /// <summary>
        /// This replaces this <see cref="SvgRectF"/> structure with the 
        /// intersection of itself and the specified <see cref="SvgRectF"/> 
        /// structure.
        /// </summary>
        /// <param name="rect">The rectangle to intersect. </param>
        /// <returns>This method does not return a value.</returns>
        public void Intersection(SvgRectF rect)
        {
            SvgRectF result = SvgRectF.Intersection(rect, this);
            _x      = result.X;
            _y      = result.Y;
            _width  = result.Width;
            _height = result.Height;
        }

        /// <summary>
        /// This determines if this rectangle intersects with rect.
        /// </summary>
        /// <param name="rect">The rectangle to test. </param>
        /// <returns>
        /// This method returns <see langword="true"/> if there is any 
        /// intersection; otherwise, <see langword="false"/>.
        /// </returns>
        public bool Intersects(SvgRectF rect)
        {
            if (((rect.X < (_x + _width)) && (_x < (rect.X + rect.Width))) && 
                (rect.Y < (_y + _height)))
            {
                return (_y < (rect.Y + rect.Height));
            }

            return false;
        }

        /// <overloads>
        /// Adjusts the location of this rectangle by the specified amount.
        /// </overloads>
        /// <summary>
        /// Adjusts the location of this rectangle by the specified amount.
        /// </summary>
        /// <param name="pos">The amount to offset the location. </param>
        /// <returns>This method does not return a value.</returns>
        public void Offset(SvgPointF pos)
        {
            this.Offset(pos.X, pos.Y);
        }

        /// <summary>
        /// Adjusts the location of this rectangle by the specified amount.
        /// </summary>
        /// <param name="y">The amount to offset the location vertically. </param>
        /// <param name="x">The amount to offset the location horizontally. </param>
        /// <returns>This method does not return a value.</returns>
        public void Offset(float x, float y)
        {
            _x += x;
            _y += y;
        }

        /// <summary>
        /// Converts the Location and <see cref="Size"/> of this 
        /// <see cref="SvgRectF"/> to a human-readable string.
        /// </summary>
        /// <returns>
        /// A string that contains the position, width, and height of this 
        /// <see cref="SvgRectF"/> structure; for example, 
        /// "{X=20, Y=20, Width=100, Height=50}".
        /// </returns>
        public override string ToString()
        {
            CultureInfo culture = CultureInfo.CurrentCulture;

            return ("{X=" + _x.ToString(culture) + ",Y=" + _y.ToString(culture)
                + ",Width=" + _width.ToString(culture) 
                + ",Height=" + _height.ToString(culture) + "}");
        }

        #endregion

        #region Public Operators

        /// <summary>
        /// This tests whether two <see cref="SvgRectF"/> structures have equal 
        /// location and size.
        /// </summary>
        /// <param name="left">
        /// The <see cref="SvgRectF"/> structure that is to the left of the 
        /// equality operator. 
        /// </param>
        /// <param name="right">
        /// The <see cref="SvgRectF"/> structure that is to the right of the 
        /// equality operator. 
        /// </param>
        /// <returns>
        /// This operator returns true if the two specified 
        /// <see cref="SvgRectF"/> structures have equal 
        /// <see cref="SvgRectF.X"/>, <see cref="SvgRectF.Y"/>, 
        /// <see cref="SvgRectF.Width"/>, and <see cref="SvgRectF.Height"/>
        /// properties.
        /// </returns>
        public static bool operator ==(SvgRectF left, SvgRectF right)
        {
            if (((left.X == right.X) && (left.Y == right.Y)) && 
                (left.Width == right.Width))
            {
                return (left.Height == right.Height);
            }

            return false;
        }

        /// <summary>
        /// This tests whether two <see cref="SvgRectF"/> structures differ in 
        /// location or size.</summary>
        /// <param name="left">
        /// The <see cref="SvgRectF"/> structure that is to the left of the 
        /// inequality operator. 
        /// </param>
        /// <param name="right">
        /// The <see cref="SvgRectF"/> structure that is to the right of the 
        /// inequality operator. 
        /// </param>
        /// <returns>
        /// This operator returns true if any of the <see cref="SvgRectF.X"/>, 
        /// <see cref="SvgRectF.Y"/>, <see cref="SvgRectF.Width"/>, or 
        /// <see cref="SvgRectF.Height"/> properties of the two 
        /// <see cref="SvgRectF"/> structures are unequal; otherwise false.
        /// </returns>
        public static bool operator !=(SvgRectF left, SvgRectF right)
        {
            return !(left == right);
        }

        #endregion

        #region Public Static Methods

        /// <summary>
        /// Creates and returns an inflated copy of the specified 
        /// <see cref="SvgRectF"/> structure. The copy is inflated by the 
        /// specified amount. The original rectangle remains unmodified.
        /// </summary>
        /// <param name="rect">
        /// The <see cref="SvgRectF"/> to be copied. This rectangle is not 
        /// modified. 
        /// </param>
        /// <param name="x">
        /// The amount to inflate the copy of the rectangle horizontally. 
        /// </param>
        /// <param name="y">
        /// The amount to inflate the copy of the rectangle vertically. 
        /// </param>
        /// <returns>The inflated <see cref="SvgRectF"/>.</returns>
        public static SvgRectF Inflate(SvgRectF rect, float x, float y)
        {
            SvgRectF result = rect;
            result.Inflate(x, y);

            return result;
        }

        /// <summary>
        /// Returns a <see cref="SvgRectF"/> structure that represents the 
        /// intersection of two rectangles. If there is no intersection, and 
        /// empty <see cref="SvgRectF"/> is returned.
        /// </summary>
        /// <param name="a">A rectangle to intersect. </param>
        /// <param name="b">A rectangle to intersect. </param>
        /// <returns>
        /// A third <see cref="SvgRectF"/> structure the size of which 
        /// represents the overlapped area of the two specified rectangles.
        /// </returns>
        public static SvgRectF Intersection(SvgRectF a, SvgRectF b)
        {
            float dLeft   = Math.Max(a.X, b.X);
            float dRight  = Math.Min(a.X + a.Width, b.X + b.Width);
            float dTop    = Math.Max(a.Y, b.Y);
            float dBottom = Math.Min(a.Y + a.Height, b.Y + b.Height);
            if ((dRight >= dLeft) && (dBottom >= dTop))
            {
                return new SvgRectF(dLeft, dTop, dRight - dLeft,
                    dBottom - dTop);
            }

            return SvgRectF.Empty;
        }

        /// <summary>
        /// Creates the smallest possible third rectangle that can contain both 
        /// of two rectangles that form a union.
        /// </summary>
        /// <param name="a">A rectangle to union. </param>
        /// <param name="b">A rectangle to union. </param>
        /// <returns>
        /// A third <see cref="SvgRectF"/> structure that contains both of 
        /// the two rectangles that form the union.
        /// </returns>
        public static SvgRectF Union(SvgRectF a, SvgRectF b)
        {
            float dLeft   = Math.Min(a.X, b.X);
            float dRight  = Math.Max(a.X + a.Width, b.X + b.Width);
            float dTop    = Math.Min(a.Y, b.Y);
            float dBottom = Math.Max(a.Y + a.Height, b.Y + b.Height);

            return new SvgRectF(dLeft, dTop, dRight - dLeft, dBottom - dTop);
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The BSD License


Written By
Engineer
Japan Japan
Systems Engineer

Comments and Discussions