123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Text;
- using System.Reflection;
- using System.ComponentModel;
- using Svg.DataTypes;
- using System.Text.RegularExpressions;
- using System.Linq;
- #pragma warning disable
- namespace Svg
- {
- public partial class SvgElement
- {
- private bool _dirty;
- /// <summary>
- /// Gets or sets a value indicating whether this element's <see cref="Path"/> is dirty.
- /// </summary>
- /// <value>
- /// <c>true</c> if the path is dirty; otherwise, <c>false</c>.
- /// </value>
- protected virtual bool IsPathDirty
- {
- get { return this._dirty; }
- set { this._dirty = value; }
- }
- /// <summary>
- /// Force recreation of the paths for the element and it's children.
- /// </summary>
- public void InvalidateChildPaths()
- {
- this.IsPathDirty = true;
- foreach (SvgElement element in this.Children)
- {
- element.InvalidateChildPaths();
- }
- }
- protected static float FixOpacityValue(float value)
- {
- const float max = 1.0f;
- const float min = 0.0f;
- return Math.Min(Math.Max(value, min), max);
- }
- /// <summary>
- /// Gets or sets the fill <see cref="SvgPaintServer"/> of this element.
- /// </summary>
- [SvgAttribute("fill", true)]
- public virtual SvgPaintServer Fill
- {
- get
- {
- if (this.Attributes["fill"] == null)
- return SvgColourServer.NotSet;
- else
- return (SvgPaintServer)this.Attributes["fill"];
- }
- set { this.Attributes["fill"] = value; }
- }
- /// <summary>
- /// Gets or sets the <see cref="SvgPaintServer"/> to be used when rendering a stroke around this element.
- /// </summary>
- [SvgAttribute("stroke", true)]
- public virtual SvgPaintServer Stroke
- {
- get { return (SvgPaintServer)this.Attributes["stroke"]; }
- set { this.Attributes["stroke"] = value; }
- }
- [SvgAttribute("fill-rule", true)]
- public virtual SvgFillRule FillRule
- {
- get
- {
- if (this.Attributes["fill-rule"] == null)
- return SvgFillRule.NonZero;
- else
- return (SvgFillRule)this.Attributes["fill-rule"];
- }
- set { this.Attributes["fill-rule"] = value; }
- }
- /// <summary>
- /// Gets or sets the opacity of this element's <see cref="Fill"/>.
- /// </summary>
- [SvgAttribute("fill-opacity", true)]
- public virtual float FillOpacity
- {
- get
- {
- if (this.Attributes["fill-opacity"] == null)
- return 1.0f;
- else
- return (float)this.Attributes["fill-opacity"];
- }
- set { this.Attributes["fill-opacity"] = FixOpacityValue(value); }
- }
- /// <summary>
- /// Gets or sets the width of the stroke (if the <see cref="Stroke"/> property has a valid value specified.
- /// </summary>
- [SvgAttribute("stroke-width", true)]
- public virtual SvgUnit StrokeWidth
- {
- get
- {
- if (this.Attributes["stroke-width"] == null)
- return new SvgUnit(1.0f);
- else
- return (SvgUnit)this.Attributes["stroke-width"];
- }
- set { this.Attributes["stroke-width"] = value; }
- }
- [SvgAttribute("stroke-linecap", true)]
- public virtual SvgStrokeLineCap StrokeLineCap
- {
- get
- {
- if (this.Attributes["stroke-linecap"] == null)
- return SvgStrokeLineCap.Butt;
- else
- return (SvgStrokeLineCap)this.Attributes["stroke-linecap"];
- }
- set { this.Attributes["stroke-linecap"] = value; }
- }
- [SvgAttribute("stroke-linejoin", true)]
- public virtual SvgStrokeLineJoin StrokeLineJoin
- {
- get
- {
- if (this.Attributes["stroke-linejoin"] == null)
- return SvgStrokeLineJoin.Miter;
- else
- return (SvgStrokeLineJoin)this.Attributes["stroke-linejoin"];
- }
- set { this.Attributes["stroke-linejoin"] = value; }
- }
- [SvgAttribute("stroke-miterlimit", true)]
- public virtual float StrokeMiterLimit
- {
- get
- {
- if (this.Attributes["stroke-miterlimit"] == null)
- return 4f;
- else
- return (float)this.Attributes["stroke-miterlimit"];
- }
- set { this.Attributes["stroke-miterlimit"] = value; }
- }
- [SvgAttribute("stroke-dasharray", true)]
- public virtual SvgUnitCollection StrokeDashArray
- {
- get { return this.Attributes["stroke-dasharray"] as SvgUnitCollection; }
- set { this.Attributes["stroke-dasharray"] = value; }
- }
- [SvgAttribute("stroke-dashoffset", true)]
- public virtual SvgUnit StrokeDashOffset
- {
- get
- {
- if (this.Attributes["stroke-dashoffset"] == null)
- return SvgUnit.Empty;
- else
- return (SvgUnit)this.Attributes["stroke-dashoffset"];
- }
- set { this.Attributes["stroke-dashoffset"] = value; }
- }
- /// <summary>
- /// Gets or sets the opacity of the stroke, if the <see cref="Stroke"/> property has been specified. 1.0 is fully opaque; 0.0 is transparent.
- /// </summary>
- [SvgAttribute("stroke-opacity", true)]
- public virtual float StrokeOpacity
- {
- get
- {
- if (this.Attributes["stroke-opacity"] == null)
- return 1.0f;
- else
- return (float)this.Attributes["stroke-opacity"];
- }
- set { this.Attributes["stroke-opacity"] = FixOpacityValue(value); }
- }
- /// <summary>
- /// Gets or sets the colour of the gradient stop.
- /// </summary>
- [SvgAttribute("stop-color", true)]
- [TypeConverter(typeof(SvgPaintServerFactory))]
- public virtual SvgPaintServer StopColor
- {
- get { return this.Attributes["stop-color"] as SvgPaintServer; }
- set { this.Attributes["stop-color"] = value; }
- }
- /// <summary>
- /// Gets or sets the opacity of the element. 1.0 is fully opaque; 0.0 is transparent.
- /// </summary>
- [SvgAttribute("opacity", true)]
- public virtual float Opacity
- {
- get
- {
- if (this.Attributes["opacity"] == null)
- return 1.0f;
- else
- return (float)this.Attributes["opacity"];
- }
- set { this.Attributes["opacity"] = FixOpacityValue(value); }
- }
- /// <summary>
- /// Refers to the AnitAlias rendering of shapes.
- /// </summary>
- [SvgAttribute("shape-rendering")]
- public virtual SvgShapeRendering ShapeRendering
- {
- get { return this.Attributes.GetInheritedAttribute<SvgShapeRendering>("shape-rendering"); }
- set { this.Attributes["shape-rendering"] = value; }
- }
- /// <summary>
- /// Gets or sets the text anchor.
- /// </summary>
- [SvgAttribute("text-anchor", true)]
- public virtual SvgTextAnchor TextAnchor
- {
- get { return this.Attributes.GetInheritedAttribute<SvgTextAnchor>("text-anchor"); }
- set { this.Attributes["text-anchor"] = value; this.IsPathDirty = true; }
- }
- /// <summary>
- /// Specifies dominant-baseline positioning of text.
- /// </summary>
- [SvgAttribute("baseline-shift", true)]
- public virtual string BaselineShift
- {
- get { return this.Attributes.GetInheritedAttribute<string>("baseline-shift"); }
- set { this.Attributes["baseline-shift"] = value; this.IsPathDirty = true; }
- }
- /// <summary>
- /// Indicates which font family is to be used to render the text.
- /// </summary>
- [SvgAttribute("font-family", true)]
- public virtual string FontFamily
- {
- get { return this.Attributes["font-family"] as string; }
- set { this.Attributes["font-family"] = value; this.IsPathDirty = true; }
- }
- /// <summary>
- /// Refers to the size of the font from baseline to baseline when multiple lines of text are set solid in a multiline layout environment.
- /// </summary>
- [SvgAttribute("font-size", true)]
- public virtual SvgUnit FontSize
- {
- get
- {
- if (this.Attributes["font-size"] == null)
- return SvgUnit.Empty;
- else
- return (SvgUnit)this.Attributes["font-size"];
- }
- set { this.Attributes["font-size"] = value; this.IsPathDirty = true; }
- }
- /// <summary>
- /// Refers to the style of the font.
- /// </summary>
- [SvgAttribute("font-style", true)]
- public virtual SvgFontStyle FontStyle
- {
- get
- {
- if (this.Attributes["font-style"] == null)
- return SvgFontStyle.All;
- else
- return (SvgFontStyle)this.Attributes["font-style"];
- }
- set { this.Attributes["font-style"] = value; this.IsPathDirty = true; }
- }
- /// <summary>
- /// Refers to the varient of the font.
- /// </summary>
- [SvgAttribute("font-variant", true)]
- public virtual SvgFontVariant FontVariant
- {
- get
- {
- if (this.Attributes["font-variant"] == null)
- return SvgFontVariant.Inherit;
- else
- return (SvgFontVariant)this.Attributes["font-variant"];
- }
- set { this.Attributes["font-variant"] = value; this.IsPathDirty = true; }
- }
- /// <summary>
- /// Refers to the boldness of the font.
- /// </summary>
- [SvgAttribute("text-decoration", true)]
- public virtual SvgTextDecoration TextDecoration
- {
- get
- {
- if (this.Attributes["text-decoration"] == null)
- return SvgTextDecoration.Inherit;
- else
- return (SvgTextDecoration)this.Attributes["text-decoration"];
- }
- set { this.Attributes["text-decoration"] = value; this.IsPathDirty = true; }
- }
- /// <summary>
- /// Refers to the boldness of the font.
- /// </summary>
- [SvgAttribute("font-weight", true)]
- public virtual SvgFontWeight FontWeight
- {
- get
- {
- if (this.Attributes["font-weight"] == null)
- return SvgFontWeight.Inherit;
- else
- return (SvgFontWeight)this.Attributes["font-weight"];
- }
- set { this.Attributes["font-weight"] = value; this.IsPathDirty = true; }
- }
- private enum FontParseState
- {
- fontStyle,
- fontVariant,
- fontWeight,
- fontSize,
- fontFamilyNext,
- fontFamilyCurr
- }
- /// <summary>
- /// Set all font information.
- /// </summary>
- [SvgAttribute("font", true)]
- public virtual string Font
- {
- get { return ((this.Attributes["font"] ?? string.Empty) as string); }
- set
- {
- var state = FontParseState.fontStyle;
- var parts = value.Split(' ');
- SvgFontStyle fontStyle;
- SvgFontVariant fontVariant;
- SvgFontWeight fontWeight;
- SvgUnit fontSize;
- bool success;
- string[] sizes;
- string part;
- for (int i = 0; i < parts.Length; i++)
- {
- part = parts[i];
- success = false;
- while (!success)
- {
- switch (state)
- {
- case FontParseState.fontStyle:
- success = Enums.TryParse<SvgFontStyle>(part, out fontStyle);
- if (success) this.FontStyle = fontStyle;
- state++;
- break;
- case FontParseState.fontVariant:
- success = Enums.TryParse<SvgFontVariant>(part, out fontVariant);
- if (success) this.FontVariant = fontVariant;
- state++;
- break;
- case FontParseState.fontWeight:
- success = Enums.TryParse<SvgFontWeight>(part, out fontWeight);
- if (success) this.FontWeight = fontWeight;
- state++;
- break;
- case FontParseState.fontSize:
- sizes = part.Split('/');
- try
- {
- fontSize = (SvgUnit)(new SvgUnitConverter().ConvertFromInvariantString(sizes[0]));
- success = true;
- this.FontSize = fontSize;
- }
- catch { }
- state++;
- break;
- case FontParseState.fontFamilyNext:
- state++;
- success = true;
- break;
- }
- }
- switch (state)
- {
- case FontParseState.fontFamilyNext:
- this.FontFamily = string.Join(" ", parts, i + 1, parts.Length - (i + 1));
- i = int.MaxValue - 2;
- break;
- case FontParseState.fontFamilyCurr:
- this.FontFamily = string.Join(" ", parts, i, parts.Length - (i));
- i = int.MaxValue - 2;
- break;
- }
- }
- this.Attributes["font"] = value;
- this.IsPathDirty = true;
- }
- }
- /// <summary>
- /// Get the font information based on data stored with the text object or inherited from the parent.
- /// </summary>
- /// <returns></returns>
- internal IFontDefn GetFont(ISvgRenderer renderer)
- {
- // Get the font-size
- float fontSize;
- var fontSizeUnit = this.FontSize;
- if (fontSizeUnit == SvgUnit.None || fontSizeUnit == SvgUnit.Empty)
- {
- fontSize = 1.0f;
- }
- else
- {
- fontSize = fontSizeUnit.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
- }
- var family = ValidateFontFamily(this.FontFamily, this.OwnerDocument);
- var sFaces = family as IEnumerable<SvgFontFace>;
- if (sFaces == null)
- {
- var fontStyle = System.Drawing.FontStyle.Regular;
- // Get the font-weight
- switch (this.FontWeight)
- {
- //Note: Bold is not listed because it is = W700.
- case SvgFontWeight.Bolder:
- case SvgFontWeight.W600:
- case SvgFontWeight.W700:
- case SvgFontWeight.W800:
- case SvgFontWeight.W900:
- fontStyle |= System.Drawing.FontStyle.Bold;
- break;
- }
- // Get the font-style
- switch (this.FontStyle)
- {
- case SvgFontStyle.Italic:
- case SvgFontStyle.Oblique:
- fontStyle |= System.Drawing.FontStyle.Italic;
- break;
- }
- // Get the text-decoration
- switch (this.TextDecoration)
- {
- case SvgTextDecoration.LineThrough:
- fontStyle |= System.Drawing.FontStyle.Strikeout;
- break;
- case SvgTextDecoration.Underline:
- fontStyle |= System.Drawing.FontStyle.Underline;
- break;
- }
- var ff = family as FontFamily;
- if (!ff.IsStyleAvailable(fontStyle))
- {
- // Do Something
- }
- // Get the font-family
- return new GdiFontDefn(new System.Drawing.Font(ff, fontSize, fontStyle, System.Drawing.GraphicsUnit.Pixel));
- }
- else
- {
- var font = sFaces.First().Parent as SvgFont;
- if (font == null)
- {
- var uri = sFaces.First().Descendants().OfType<SvgFontFaceUri>().First().ReferencedElement;
- font = OwnerDocument.IdManager.GetElementById(uri) as SvgFont;
- }
- return new SvgFontDefn(font, fontSize, OwnerDocument.Ppi);
- }
- }
- public static object ValidateFontFamily(string fontFamilyList, SvgDocument doc)
- {
- // Split font family list on "," and then trim start and end spaces and quotes.
- var fontParts = (fontFamilyList ?? string.Empty).Split(',').Select(fontName => fontName.Trim(new[] { '"', ' ', '\'' }));
- var families = FastReport.FontManager.AllFamilies;
- Func<FontFamily, bool> getFamily;
- FontFamily family;
- IEnumerable<SvgFontFace> sFaces;
- // Find a the first font that exists in the list of installed font families.
- //styles from IE get sent through as lowercase.
- foreach (var f in fontParts)
- {
- if (doc.FontDefns().TryGetValue(f, out sFaces)) return sFaces;
- getFamily = new Func<FontFamily, bool>(ff => string.Equals(ff.Name, f, StringComparison.OrdinalIgnoreCase));
- family = families.FirstOrDefault(getFamily);
- if (family != null) return family;
- switch (f.ToLower())
- {
- case "serif":
- return System.Drawing.FontFamily.GenericSerif;
- case "sans-serif":
- return System.Drawing.FontFamily.GenericSansSerif;
- case "monospace":
- return System.Drawing.FontFamily.GenericMonospace;
- }
- }
- // No valid font family found from the list requested.
- return System.Drawing.FontFamily.GenericSansSerif;
- }
- }
- }
- #pragma warning restore
|