using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using System.ComponentModel;
using System.Diagnostics;
namespace Svg
{
///
/// The class that all SVG elements should derive from when they are to be rendered.
///
public abstract partial class SvgVisualElement : SvgElement, ISvgStylable, ISvgClipable
{
private bool _dirty;
private bool _requiresSmoothRendering;
private Region _previousClip;
private SvgClipRule clipRule = SvgClipRule.NonZero;
///
/// Gets the for this element.
///
public abstract GraphicsPath Path { get; }
///
/// Gets the bounds of the element.
///
/// The bounds.
public abstract RectangleF Bounds { get; }
///
/// Gets or sets a value indicating whether this element's is dirty.
///
///
/// true if the path is dirty; otherwise, false.
///
protected virtual bool IsPathDirty
{
get { return this._dirty; }
set { this._dirty = value; }
}
///
/// Gets the associated if one has been specified.
///
[SvgAttribute("clip-path")]
public virtual Uri ClipPath
{
get { return this.Attributes.GetAttribute("clip-path"); }
set { this.Attributes["clip-path"] = value; }
}
///
///
///
[SvgAttribute("clip-rule")]
public SvgClipRule ClipRule
{
get { return this.Attributes.GetAttribute("clip-rule", SvgClipRule.NonZero); }
set { this.Attributes["clip-rule"] = value; }
}
///
/// Gets or sets a value to determine if anti-aliasing should occur when the element is being rendered.
///
protected virtual bool RequiresSmoothRendering
{
get { return this._requiresSmoothRendering; }
}
///
/// Initializes a new instance of the class.
///
public SvgVisualElement()
{
this._dirty = true;
this._requiresSmoothRendering = false;
}
///
/// Renders the and contents to the specified object.
///
/// The object to render to.
protected override void Render(SvgRenderer renderer)
{
if (this.Path != null && this.Visible)
{
this.PushTransforms(renderer);
this.SetClip(renderer);
// If this element needs smoothing enabled turn anti aliasing on
if (this.RequiresSmoothRendering)
{
renderer.SmoothingMode = SmoothingMode.AntiAlias;
}
// Fill first so that the stroke can overlay
if (this.Fill != null)
{
using (Brush brush = this.Fill.GetBrush(this, this.FillOpacity))
{
if (brush != null)
{
renderer.FillPath(brush, this.Path);
}
}
}
// Stroke is the last thing to do
if (this.Stroke != null)
{
float strokeWidth = this.StrokeWidth.ToDeviceValue(this);
using (Pen pen = new Pen(this.Stroke.GetBrush(this, this.StrokeOpacity), strokeWidth))
{
if (pen != null)
{
if (this.StrokeDashArray != null)
{
pen.DashPattern = this.StrokeDashArray.ConvertAll(delegate(SvgUnit unit)
{
// divide by stroke width - GDI behaviour that I don't quite understand yet.
return unit.Value / ((strokeWidth <= 0) ? 1 : strokeWidth);
}).ToArray();
}
renderer.DrawPath(pen, this.Path);
}
}
}
// Reset the smoothing mode
if (this.RequiresSmoothRendering && renderer.SmoothingMode == SmoothingMode.AntiAlias)
{
renderer.SmoothingMode = SmoothingMode.Default;
}
this.ResetClip(renderer);
this.PopTransforms(renderer);
}
}
///
/// Sets the clipping region of the specified .
///
/// The to have its clipping region set.
protected internal virtual void SetClip(SvgRenderer renderer)
{
if (this.ClipPath != null)
{
SvgClipPath clipPath = this.OwnerDocument.GetElementById(this.ClipPath.ToString());
this._previousClip = renderer.Clip;
if (clipPath != null)
{
renderer.Clip = clipPath.GetClipRegion(this);
}
}
}
///
/// Resets the clipping region of the specified back to where it was before the method was called.
///
/// The to have its clipping region reset.
protected internal virtual void ResetClip(SvgRenderer renderer)
{
if (this._previousClip != null)
{
renderer.Clip = this._previousClip;
this._previousClip = null;
}
}
///
/// Sets the clipping region of the specified .
///
/// The to have its clipping region set.
void ISvgClipable.SetClip(SvgRenderer renderer)
{
this.SetClip(renderer);
}
///
/// Resets the clipping region of the specified back to where it was before the method was called.
///
/// The to have its clipping region reset.
void ISvgClipable.ResetClip(SvgRenderer renderer)
{
this.ResetClip(renderer);
}
}
}