private static void SetAttributes(SvgElement element, XmlTextReader reader, SvgDocument document) { //Trace.TraceInformation("Begin SetAttributes"); string[] styles = null; string[] style = null; int i = 0; while (reader.MoveToNextAttribute()) { // Special treatment for "style" if (reader.LocalName.Equals("style")) { styles = reader.Value.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (i = 0; i < styles.Length; i++) { if (!styles[i].Contains(":")) { continue; } style = styles[i].Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries); SetPropertyValue(element, style[0].Trim(), style[1].Trim(), document); } continue; } SetPropertyValue(element, reader.LocalName, reader.Value, document); } //Trace.TraceInformation("End SetAttributes"); }
public PointF ToDeviceValue(SvgRenderer renderer, SvgElement owner) { return SvgUnit.GetDevicePoint(this.X, this.Y, renderer, owner); }
private static void SetPropertyValue(SvgElement element, string attributeName, string attributeValue, SvgDocument document) { var elementType = element.GetType(); PropertyDescriptorCollection properties; if (_propertyDescriptors.Keys.Contains(elementType)) { if (_propertyDescriptors[elementType].Keys.Contains(attributeName)) { properties = _propertyDescriptors[elementType][attributeName]; } else { properties = TypeDescriptor.GetProperties(elementType, new[] { new SvgAttributeAttribute(attributeName) }); _propertyDescriptors[elementType].Add(attributeName, properties); } } else { properties = TypeDescriptor.GetProperties(element.GetType(), new[] { new SvgAttributeAttribute(attributeName) }); _propertyDescriptors.Add(elementType, new Dictionary<string, PropertyDescriptorCollection>()); _propertyDescriptors[elementType].Add(attributeName, properties); } if (properties.Count > 0) { PropertyDescriptor descriptor = properties[0]; try { descriptor.SetValue(element, descriptor.Converter.ConvertFrom(document, CultureInfo.InvariantCulture, attributeValue)); } catch { Trace.TraceWarning(string.Format("Attribute '{0}' cannot be set - type '{1}' cannot convert from string '{2}'.", attributeName, descriptor.PropertyType.FullName, attributeValue)); } } }
/// <summary> /// Removed the specified <see cref="SvgElement"/> from ID management. /// </summary> /// <param name="element">The <see cref="SvgElement"/> to be removed from ID management.</param> public virtual void Remove(SvgElement element) { if (!string.IsNullOrEmpty(element.ID)) { this._idValueMap.Remove(element.ID); } }
/// <summary> /// /// </summary> /// <param name="region"></param> /// <param name="element"></param> private void CombinePaths(GraphicsPath path, SvgElement element) { var graphicsElement = element as SvgVisualElement; if (graphicsElement != null && graphicsElement.Path != null) { path.FillMode = (graphicsElement.ClipRule == SvgClipRule.NonZero) ? FillMode.Winding : FillMode.Alternate; GraphicsPath childPath = graphicsElement.Path; if (graphicsElement.Transforms != null) { foreach (SvgTransform transform in graphicsElement.Transforms) { childPath.Transform(transform.Matrix); } } path.AddPath(childPath, false); } foreach (SvgElement child in element.Children) { this.CombinePaths(path, child); } }
private void UpdateStrokeColor(SvgLib.SvgElement el, ColorManagement colorManagement) { if (el is SvgLib.SvgCircle || el is SvgLib.SvgEllipse || el is SvgLib.SvgLine || el is SvgLib.SvgPath || el is SvgLib.SvgPolygon || el is SvgLib.SvgPolyline || el is SvgLib.SvgRectangle) { var stroke = (el as SvgLib.SvgVisualElement).Stroke; if (stroke != null) { System.Drawing.Color color; if (StrokeColor is RgbColor) { color = StrokeColor.ToGdiPlusColor(); } else { colorManagement = colorManagement ?? GetColorManagement(true); color = ColorManagement.GetPreviewColor(colorManagement, _strokeColor); } (stroke as SvgLib.SvgColourServer).Colour = color; } } if (el.HasChildren()) { foreach (var ch in el.Children) { UpdateStrokeColor(ch, colorManagement); } } }
private System.Drawing.Color GetStrokeColorFromSvg(SvgLib.SvgElement el) { if (el is SvgLib.SvgVisualElement) { var stroke = (el as SvgLib.SvgVisualElement).Stroke; if (stroke != null) { return((stroke as SvgLib.SvgColourServer).Colour); } } if (el.HasChildren()) { foreach (var ch in el.Children) { var result = GetStrokeColorFromSvg(ch); if (!result.IsEmpty) { return(result); } } } return(System.Drawing.Color.Empty); }
public void ParseElements(ISvgEventCaller caller, SvgElement element) { //register events if(element.HasNonEmptyCustomAttribute("onclick")) { element.RegisterEvents(caller); element.Click += child_Click; } //gather color relevant elements if(element.HasNonEmptyCustomAttribute("class")) { if(element.CustomAttributes["class"] == "widgetback") if(element is SvgVisualElement) BackgroundElements.Add(element as SvgVisualElement); else if(element.CustomAttributes["class"] == "widgetfore") if(element is SvgVisualElement) ForegroundElements.Add(element as SvgVisualElement); } foreach (var child in element.Children) { ParseElements(caller, child); } }
/// <summary> /// Изменить цвет у элемента /// </summary> /// <param name="element">SvgElement</param> /// <param name="sourceColor">Реальный цвет</param> /// <param name="replaceColor">Новый цвет</param> private void ChangeSvgElementColor(SvgElement element, Color? sourceColor, Color replaceColor) { if (element is SvgPath) { if (sourceColor.HasValue) { if (((element as SvgPath).Fill as SvgColourServer).Colour.ToArgb() == sourceColor.Value.ToArgb()) { (element as SvgPath).Fill = new SvgColourServer(replaceColor); } } else { (element as SvgPath).Fill = new SvgColourServer(replaceColor); } } if (element.Children.Count > 0) { foreach (var item in element.Children) { ChangeSvgElementColor(item, sourceColor, replaceColor); } } }
/// <summary> /// Adds the specified <see cref="SvgElement"/> for ID management. /// </summary> /// <param name="element">The <see cref="SvgElement"/> to be managed.</param> public virtual void Add(SvgElement element) { if (!string.IsNullOrEmpty(element.ID)) { this.EnsureValidId(element.ID); this._idValueMap.Add(element.ID, element); } }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been added to the /// <see cref="Children"/> collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been added.</param> /// <param name="index">An <see cref="int"/> representing the index where the element was added to the collection.</param> protected override void AddElement(SvgElement child, int index) { if (child is SvgGradientStop) { this.Stops.Add((SvgGradientStop)child); } base.AddElement(child, index); }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been removed from the /// <see cref="Children"/> collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been removed.</param> protected override void RemoveElement(SvgElement child) { if (child is SvgGradientStop) { this.Stops.Remove((SvgGradientStop)child); } base.RemoveElement(child); }
void UnregisterElementEvents(ISvgEventCaller caller, SvgElement element) { element.UnregisterEvents(caller); foreach (var child in element.Children) { UnregisterElementEvents(caller, child); } }
public override void Remove(SvgElement element) { element.AttributeChanged -= element_AttributeChanged; element.ContentChanged -= element_ContentChanged; element.ChildAdded -= element_ChildAdded; if(element is SvgVisualElement) element.UnregisterEvents(FCaller); if(!string.IsNullOrWhiteSpace(element.ID)) RemoteContext.AddRemoveElement(element); base.Remove(element); }
/// <summary> /// /// </summary> /// <param name="region"></param> /// <param name="element"></param> private void CombinePaths(GraphicsPath path, SvgElement element) { var graphicsElement = element as SvgVisualElement; if (graphicsElement != null && graphicsElement.Path != null) { path.FillMode = (graphicsElement.ClipRule == SvgClipRule.NonZero) ? FillMode.Winding : FillMode.Alternate; path.AddPath(graphicsElement.Path, false); } foreach (SvgElement child in element.Children) { this.CombinePaths(path, child); } }
/// <summary> /// Adds the specified <see cref="SvgElement"/> for ID management. /// And can auto fix the ID if it already exists or it starts with a number. /// </summary> /// <param name="element">The <see cref="SvgElement"/> to be managed.</param> /// <param name="autoFixID">Pass true here, if you want the ID to be fixed</param> /// <param name="logElementOldIDNewID">If not null, the action is called before the id is fixed</param> /// <returns>true, if ID was altered</returns> public virtual bool AddAndFixID(SvgElement element, bool autoFixID = true, Action<SvgElement, string, string> logElementOldIDNewID = null) { var result = false; if (!string.IsNullOrEmpty(element.ID)) { var newID = this.EnsureValidId(element.ID, autoFixID); if (autoFixID && newID != element.ID) { if(logElementOldIDNewID != null) logElementOldIDNewID(element, element.ID, newID); element.FixID(newID); result = true; } this._idValueMap.Add(element.ID, element); } OnAdded(element); return result; }
public override bool AddAndForceUniqueID(SvgElement element, SvgElement sibling, bool autoForceUniqueID, Action<SvgElement, string, string> logElementOldIDNewID) { //register events element.AttributeChanged += element_AttributeChanged; element.ContentChanged += element_ContentChanged; element.ChildAdded += element_ChildAdded; if(element is SvgVisualElement) { //check id if(string.IsNullOrWhiteSpace(element.ID)) { if(element.Parent != null) element.SetAndForceUniqueID(element.Parent.ID + "_" + IDGenerator.NewID, true, null); else element.SetAndForceUniqueID(RandomString(16), true, null); } } return base.AddAndForceUniqueID(element, sibling, true, logElementOldIDNewID); }
public static System.Drawing.PointF GetDevicePointOffset(SvgUnit x, SvgUnit y, ISvgRenderer renderer, SvgElement owner) { return new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner), y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner)); }
/// <summary> /// Converts the current unit to one that can be used at render time. /// </summary> /// <param name="boundable">The container element used as the basis for calculations</param> /// <returns>The representation of the current unit in a device value (usually pixels).</returns> public float ToDeviceValue(ISvgRenderer renderer, UnitRenderingType renderType, SvgElement owner) { // If it's already been calculated if (this._deviceValue.HasValue) { return(this._deviceValue.Value); } if (this._value == 0.0f) { this._deviceValue = 0.0f; return(this._deviceValue.Value); } // http://www.w3.org/TR/CSS21/syndata.html#values // http://www.w3.org/TR/SVG11/coords.html#Units const float cmInInch = 2.54f; int ppi = owner != null ? owner.OwnerDocument.Ppi : SvgDocument.PointsPerInch; var type = this.Type; var value = this.Value; float points; switch (type) { case SvgUnitType.Em: using (var currFont = GetFont(renderer, owner)) { if (currFont == null) { points = (float)(value * 9); _deviceValue = (points / 72.0f) * ppi; } else { _deviceValue = value * (currFont.SizeInPoints / 72.0f) * ppi; } } break; case SvgUnitType.Ex: using (var currFont = GetFont(renderer, owner)) { if (currFont == null) { points = (float)(value * 9); _deviceValue = (points * 0.5f / 72.0f) * ppi; } else { _deviceValue = value * 0.5f * (currFont.SizeInPoints / 72.0f) * ppi; } break; } case SvgUnitType.Centimeter: _deviceValue = (float)((value / cmInInch) * ppi); break; case SvgUnitType.Inch: _deviceValue = value * ppi; break; case SvgUnitType.Millimeter: _deviceValue = (float)((value / 10) / cmInInch) * ppi; break; case SvgUnitType.Pica: _deviceValue = ((value * 12) / 72) * ppi; break; case SvgUnitType.Point: _deviceValue = (value / 72) * ppi; break; case SvgUnitType.Pixel: _deviceValue = value; break; case SvgUnitType.User: _deviceValue = value; break; case SvgUnitType.Percentage: // Can't calculate if there is no style owner var boundable = (renderer == null ? (owner == null ? null : owner.OwnerDocument) : renderer.GetBoundable()); if (boundable == null) { _deviceValue = value; break; } System.Drawing.SizeF size = boundable.Bounds.Size; switch (renderType) { case UnitRenderingType.Horizontal: _deviceValue = (size.Width / 100) * value; break; case UnitRenderingType.HorizontalOffset: _deviceValue = (size.Width / 100) * value + boundable.Location.X; break; case UnitRenderingType.Vertical: _deviceValue = (size.Height / 100) * value; break; case UnitRenderingType.VerticalOffset: _deviceValue = (size.Height / 100) * value + boundable.Location.Y; break; default: _deviceValue = (float)(Math.Sqrt(Math.Pow(size.Width, 2) + Math.Pow(size.Height, 2)) / Math.Sqrt(2) * value / 100.0); break; } break; default: _deviceValue = value; break; } return(this._deviceValue.Value); }
public static System.Drawing.PointF GetDevicePointOffset(SvgUnit x, SvgUnit y, ISvgRenderer renderer, SvgElement owner) { return(new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner), y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner))); }
public static bool HasNonEmptyCustomAttribute(this SvgElement element, string name) { return(element.CustomAttributes.ContainsKey(name) && !string.IsNullOrEmpty(element.CustomAttributes[name])); }
protected bool ExistsContentElement(SvgElement elem) { //needs id if(string.IsNullOrEmpty(elem.ID)) return true; return ContentElements.Contains(elem); }
/// <summary> /// Adds the specified <see cref="SvgElement"/> for ID management. /// </summary> /// <param name="element">The <see cref="SvgElement"/> to be managed.</param> public virtual void Add(SvgElement element) { AddAndForceUniqueID(element, null, false); }
/// <summary> /// Given the SVG/XML fragment return a fully populated SVG node. The returned node is not added to the given document /// </summary> /// <param name="document">The document context to parse the in content in</param> /// <param name="fragment">The SVG/XML formatted string to parse</param> /// <param name="entities">Optional dictionary to resolve entities. May be null.</param> /// <returns></returns> public SvgElement[] ParseFragment(SvgDocument document, string fragment, Dictionary <string, string> entities) { NameTable nt = new NameTable(); XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt); nsmgr.AddNamespace("svg", svgNS); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); using (var reader = new SvgTextReader(fragment, XmlNodeType.Element, context, entities)) { var elements = new List <SvgElement>(); var elementStack = new Stack <SvgElement>(); var value = new StringBuilder(); bool elementEmpty; SvgElement element = null; while (reader.Read()) { 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) elementEmpty = reader.IsEmptyElement; // Create element element = CreateElement(reader, document); // Add to the parents children if (elementStack.Count > 0) { var parent = elementStack.Peek(); if (parent != null && element != null) { parent.Children.Add(element); } } else { elements.Add(element); } // Push element into stack elementStack.Push(element); // Need to process if the element is empty if (elementEmpty) { goto case XmlNodeType.EndElement; } break; case XmlNodeType.EndElement: // Pop the element out of the stack element = elementStack.Pop(); if (value.Length > 0 && element != null) { element.Content = value.ToString(); // Reset content value for new element value.Clear(); } break; case XmlNodeType.CDATA: case XmlNodeType.Text: value.Append(reader.Value); break; } } return(elements.ToArray()); } }
/// <summary> /// Opens an SVG document from the specified <see cref="Stream"/> and adds the specified entities. /// </summary> /// <param name="stream">The <see cref="Stream"/> containing the SVG document to open.</param> /// <param name="entities">Custom entity definitions.</param> /// <exception cref="ArgumentNullException">The <paramref name="stream"/> parameter cannot be <c>null</c>.</exception> public static SvgDocument Open(Stream stream, Dictionary <string, string> entities) { if (stream == null) { throw new ArgumentNullException("stream"); } //Trace.TraceInformation("Begin Read"); using (var reader = new SvgTextReader(stream, entities)) { var elementStack = new Stack <SvgElement>(); var value = new StringBuilder(); bool elementEmpty; SvgElement element = null; SvgElement parent; 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) elementEmpty = reader.IsEmptyElement; // Create element if (elementStack.Count > 0) { element = SvgElementFactory.CreateElement(reader, svgDocument); } else { element = SvgElementFactory.CreateDocument(reader); svgDocument = (SvgDocument)element; } 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 (elementEmpty) { goto case XmlNodeType.EndElement; } break; case XmlNodeType.EndElement: // Skip if no element was created and is not the closing tag for the last // known element if (element == null && reader.LocalName != elementStack.Peek().ElementName) { 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); } }
private static T Open <T>(XmlReader reader) where T : SvgDocument, new() { if (!SkipGdiPlusCapabilityCheck) { EnsureSystemIsGdiPlusCapable(); //Validate whether the GDI+ can be loaded, this will yield an exception if not } var elementStack = new Stack <SvgElement>(); bool elementEmpty; SvgElement element = null; SvgElement parent; T svgDocument = null; var elementFactory = new SvgElementFactory(); var styles = new List <ISvgNode>(); 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) elementEmpty = reader.IsEmptyElement; // Create element if (elementStack.Count > 0) { element = elementFactory.CreateElement(reader, svgDocument); } else { svgDocument = elementFactory.CreateDocument <T>(reader); element = svgDocument; } // Add to the parents children if (elementStack.Count > 0) { parent = elementStack.Peek(); if (parent != null && element != null) { parent.Children.Add(element); parent.Nodes.Add(element); } } // Push element into stack elementStack.Push(element); // Need to process if the element is empty if (elementEmpty) { goto case XmlNodeType.EndElement; } break; case XmlNodeType.EndElement: // Pop the element out of the stack element = elementStack.Pop(); if (element.Nodes.OfType <SvgContentNode>().Any()) { element.Content = (from e in element.Nodes select e.Content).Aggregate((p, c) => p + c); } else { element.Nodes.Clear(); // No sense wasting the space where it isn't needed } var unknown = element as SvgUnknownElement; if (unknown != null && unknown.ElementName == "style") { styles.Add(unknown); } break; case XmlNodeType.CDATA: case XmlNodeType.Text: case XmlNodeType.SignificantWhitespace: element = elementStack.Peek(); element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); break; case XmlNodeType.EntityReference: reader.ResolveEntity(); element = elementStack.Peek(); element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); break; } } catch (Exception exc) { Trace.TraceError(exc.Message); } } if (styles.Any()) { var cssTotal = styles.Select((s) => s.Content).Aggregate((p, c) => p + Environment.NewLine + c); var cssParser = new Parser(); var sheet = cssParser.Parse(cssTotal ?? string.Empty); foreach (var rule in sheet.StyleRules) { try { var rootNode = new NonSvgElement(); rootNode.Children.Add(svgDocument); var elemsToStyle = rootNode.QuerySelectorAll(rule.Selector.ToString(), elementFactory); foreach (var elem in elemsToStyle) { foreach (var decl in rule.Declarations) { elem.AddStyle(decl.Name, decl.Term.ToString(), rule.Selector.GetSpecificity()); } } } catch (Exception ex) { Trace.TraceWarning(ex.Message); } } } svgDocument?.FlushStyles(true); return(svgDocument); }
internal static bool SetPropertyValue(SvgElement element, string attributeName, string attributeValue, SvgDocument document, bool isStyle = false) { #if !USE_SOURCE_GENERATORS var elementType = element.GetType(); PropertyDescriptorCollection properties; lock (syncLock) { if (_propertyDescriptors.Keys.Contains(elementType)) { if (_propertyDescriptors[elementType].Keys.Contains(attributeName)) { properties = _propertyDescriptors[elementType][attributeName]; } else { properties = TypeDescriptor.GetProperties(elementType, new[] { new SvgAttributeAttribute(attributeName) }); _propertyDescriptors[elementType].Add(attributeName, properties); } } else { properties = TypeDescriptor.GetProperties(elementType, new[] { new SvgAttributeAttribute(attributeName) }); _propertyDescriptors.Add(elementType, new Dictionary <string, PropertyDescriptorCollection>()); _propertyDescriptors[elementType].Add(attributeName, properties); } } if (properties.Count > 0) { PropertyDescriptor descriptor = properties[0]; try { if (attributeName == "opacity" && attributeValue == "undefined") { attributeValue = "1"; } descriptor.SetValue(element, descriptor.Converter.ConvertFrom(document, CultureInfo.InvariantCulture, attributeValue)); } catch { Trace.TraceWarning(string.Format("Attribute '{0}' cannot be set - type '{1}' cannot convert from string '{2}'.", attributeName, descriptor.PropertyType.FullName, attributeValue)); } } else #else if (attributeName == "opacity" && attributeValue == "undefined") { attributeValue = "1"; } var setValueResult = element.SetValue(attributeName, document, CultureInfo.InvariantCulture, attributeValue); if (setValueResult) { return(true); } #endif { //check for namespace declaration in svg element if (string.Equals(element.ElementName, "svg", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(attributeName, "xmlns", StringComparison.OrdinalIgnoreCase) || string.Equals(attributeName, "xlink", StringComparison.OrdinalIgnoreCase) || string.Equals(attributeName, "xmlns:xlink", StringComparison.OrdinalIgnoreCase) || string.Equals(attributeName, "version", StringComparison.OrdinalIgnoreCase)) { //nothing to do } else { //attribute is not a svg attribute, store it in custom attributes element.CustomAttributes[attributeName] = attributeValue; } } else { if (isStyle) { // custom styles shall remain as style return(false); } //attribute is not a svg attribute, store it in custom attributes element.CustomAttributes[attributeName] = attributeValue; } } return(true); }
/// <summary> /// Converts the current unit to one that can be used at render time. /// </summary> /// <param name="boundable">The container element used as the basis for calculations</param> /// <returns>The representation of the current unit in a device value (usually pixels).</returns> public float ToDeviceValue(SvgRenderer renderer, UnitRenderingType renderType, SvgElement owner) { // If it's already been calculated if (this._deviceValue.HasValue) { return this._deviceValue.Value; } if (this._value == 0.0f) { this._deviceValue = 0.0f; return this._deviceValue.Value; } // http://www.w3.org/TR/CSS21/syndata.html#values // http://www.w3.org/TR/SVG11/coords.html#Units const float cmInInch = 2.54f; int ppi = SvgDocument.PointsPerInch; var type = this.Type; var value = this.Value; // Deal with fractional pattern units var coordElem = owner as ISvgSupportsCoordinateUnits; if (coordElem != null && coordElem.GetUnits() == SvgCoordinateUnits.ObjectBoundingBox && type != SvgUnitType.Percentage) { type = SvgUnitType.Percentage; value *= 100; } var element = owner as SvgElement; if (element != null) { var pattern = element.Parents.OfType<SvgPatternServer>().FirstOrDefault(); if (pattern != null && pattern.PatternContentUnits == SvgCoordinateUnits.ObjectBoundingBox && type != SvgUnitType.Percentage) { type = SvgUnitType.Percentage; value *= 100; } } float points; Font currFont; switch (type) { case SvgUnitType.Em: currFont = GetFont(renderer, owner); if (currFont == null) { points = (float)(value * 9); _deviceValue = (points / 72.0f) * ppi; } else { _deviceValue = value * (currFont.SizeInPoints / 72.0f) * ppi; } break; case SvgUnitType.Ex: currFont = GetFont(renderer, owner); if (currFont == null) { points = (float)(value * 9); _deviceValue = (points * 0.5f / 72.0f) * ppi; } else { _deviceValue = value * 0.5f * (currFont.SizeInPoints / 72.0f) * ppi; } break; case SvgUnitType.Centimeter: _deviceValue = (float)((value / cmInInch) * ppi); break; case SvgUnitType.Inch: _deviceValue = value * ppi; break; case SvgUnitType.Millimeter: _deviceValue = (float)((value / 10) / cmInInch) * ppi; break; case SvgUnitType.Pica: _deviceValue = ((value * 12) / 72) * ppi; break; case SvgUnitType.Point: _deviceValue = (value / 72) * ppi; break; case SvgUnitType.Pixel: _deviceValue = value; break; case SvgUnitType.User: _deviceValue = value; break; case SvgUnitType.Percentage: // Can't calculate if there is no style owner var boundable = (renderer == null ? (owner == null ? null : owner.OwnerDocument) : renderer.Boundable()); if (boundable == null) { _deviceValue = value; break; } System.Drawing.SizeF size = boundable.Bounds.Size; switch (renderType) { case UnitRenderingType.Horizontal: _deviceValue = (size.Width / 100) * value; break; case UnitRenderingType.HorizontalOffset: _deviceValue = (size.Width / 100) * value + boundable.Location.X; break; case UnitRenderingType.Vertical: _deviceValue = (size.Height / 100) * value; break; case UnitRenderingType.VerticalOffset: _deviceValue = (size.Height / 100) * value + boundable.Location.Y; break; default: _deviceValue = (float)(Math.Sqrt(Math.Pow(size.Width, 2) + Math.Pow(size.Height, 2)) / Math.Sqrt(2) * value / 100.0); break; } break; default: _deviceValue = value; break; } return this._deviceValue.Value; }
/// <summary> /// Converts the current unit to one that can be used at render time. /// </summary> /// <param name="boundable">The container element used as the basis for calculations</param> /// <returns>The representation of the current unit in a device value (usually pixels).</returns> public float ToDeviceValue(ISvgRenderer renderer, UnitRenderingType renderType, SvgElement owner) { // If it's already been calculated if (this._deviceValue.HasValue) { return this._deviceValue.Value; } if (this._value == 0.0f) { this._deviceValue = 0.0f; return this._deviceValue.Value; } // http://www.w3.org/TR/CSS21/syndata.html#values // http://www.w3.org/TR/SVG11/coords.html#Units const float cmInInch = 2.54f; int ppi = SvgDocument.PointsPerInch; var type = this.Type; var value = this.Value; float points; switch (type) { case SvgUnitType.Em: using (var currFont = GetFont(renderer, owner)) { if (currFont == null) { points = (float)(value * 9); _deviceValue = (points / 72.0f) * ppi; } else { _deviceValue = value * (currFont.SizeInPoints / 72.0f) * ppi; } } break; case SvgUnitType.Ex: using (var currFont = GetFont(renderer, owner)) { if (currFont == null) { points = (float)(value * 9); _deviceValue = (points * 0.5f / 72.0f) * ppi; } else { _deviceValue = value * 0.5f * (currFont.SizeInPoints / 72.0f) * ppi; } break; } case SvgUnitType.Centimeter: _deviceValue = (float)((value / cmInInch) * ppi); break; case SvgUnitType.Inch: _deviceValue = value * ppi; break; case SvgUnitType.Millimeter: _deviceValue = (float)((value / 10) / cmInInch) * ppi; break; case SvgUnitType.Pica: _deviceValue = ((value * 12) / 72) * ppi; break; case SvgUnitType.Point: _deviceValue = (value / 72) * ppi; break; case SvgUnitType.Pixel: _deviceValue = value; break; case SvgUnitType.User: _deviceValue = value; break; case SvgUnitType.Percentage: // Can't calculate if there is no style owner var boundable = (renderer == null ? (owner == null ? null : owner.OwnerDocument) : renderer.GetBoundable()); if (boundable == null) { _deviceValue = value; break; } System.Drawing.SizeF size = boundable.Bounds.Size; switch (renderType) { case UnitRenderingType.Horizontal: _deviceValue = (size.Width / 100) * value; break; case UnitRenderingType.HorizontalOffset: _deviceValue = (size.Width / 100) * value + boundable.Location.X; break; case UnitRenderingType.Vertical: _deviceValue = (size.Height / 100) * value; break; case UnitRenderingType.VerticalOffset: _deviceValue = (size.Height / 100) * value + boundable.Location.Y; break; default: _deviceValue = (float)(Math.Sqrt(Math.Pow(size.Width, 2) + Math.Pow(size.Height, 2)) / Math.Sqrt(2) * value / 100.0); break; } break; default: _deviceValue = value; break; } return this._deviceValue.Value; }
private void AddChild(SvgElement element) { var group = _currentImage.Children.GetSvgElementOf<SvgGroup>(); if (group == null) { group = new SvgGroup(); _currentImage.Children.Add(group); } group.Children.Add(element); }
/// <summary> /// Converts the current unit to one that can be used at render time. /// </summary> /// <returns>The representation of the current unit in a device value (usually pixels).</returns> public float ToDeviceValue(ISvgRenderer renderer, UnitRenderingType renderType, SvgElement owner) { // If it's already been calculated if (this._deviceValue.HasValue) { return(this._deviceValue.Value); } if (this._value == 0.0f) { this._deviceValue = 0.0f; return(this._deviceValue.Value); } // http://www.w3.org/TR/CSS21/syndata.html#values // http://www.w3.org/TR/SVG11/coords.html#Units const float cmInInch = 2.54f; int ppi = SvgDocument.PointsPerInch; var type = this.Type; var value = this.Value; switch (type) { case SvgUnitType.Em: _deviceValue = value; break; case SvgUnitType.Ex: _deviceValue = value; break; case SvgUnitType.Centimeter: _deviceValue = (float)((value / cmInInch) * ppi); break; case SvgUnitType.Inch: _deviceValue = value * ppi; break; case SvgUnitType.Millimeter: _deviceValue = (float)((value / 10) / cmInInch) * ppi; break; case SvgUnitType.Pica: _deviceValue = ((value * 12) / 72) * ppi; break; case SvgUnitType.Point: _deviceValue = (value / 72) * ppi; break; case SvgUnitType.Pixel: _deviceValue = value; break; case SvgUnitType.User: _deviceValue = value; break; case SvgUnitType.Percentage: _deviceValue = value; break; default: _deviceValue = value; break; } return(this._deviceValue.Value); }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been added to the /// <see cref="Children"/> collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been added.</param> /// <param name="index">An <see cref="int"/> representing the index where the element was added to the collection.</param> protected override void AddElement(SvgElement child, int index) { base.AddElement(child, index); this._pathDirty = true; }
public static Vector2 GetDevicePointOffset(SvgUnit x, SvgUnit y, ISvgRenderer renderer, SvgElement owner) { return(new Vector2(x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner), y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner))); }
/// <summary> /// Adds the specified <see cref="SvgElement"/> for ID management. /// </summary> /// <param name="element">The <see cref="SvgElement"/> to be managed.</param> public virtual void Add(SvgElement element) { AddAndFixID(element, false); }
private Font GetFont(SvgRenderer renderer, SvgElement owner) { if (owner == null) return null; var visual = owner.ParentsAndSelf.OfType<SvgVisualElement>().FirstOrDefault(); return visual.GetFont(renderer); }
/// <summary> /// Converts the current unit to one that can be used at render time. /// </summary> /// <param name="boundable">The container element used as the basis for calculations</param> /// <returns>The representation of the current unit in a device value (usually pixels).</returns> public float ToDeviceValue(SvgRenderer renderer, UnitRenderingType renderType, SvgElement owner) { // If it's already been calculated if (this._deviceValue.HasValue) { return(this._deviceValue.Value); } if (this._value == 0.0f) { this._deviceValue = 0.0f; return(this._deviceValue.Value); } // http://www.w3.org/TR/CSS21/syndata.html#values // http://www.w3.org/TR/SVG11/coords.html#Units const float cmInInch = 2.54f; int ppi = SvgDocument.PointsPerInch; var type = this.Type; var value = this.Value; // Deal with fractional pattern units var coordElem = owner as ISvgSupportsCoordinateUnits; if (coordElem != null && coordElem.GetUnits() == SvgCoordinateUnits.ObjectBoundingBox && type != SvgUnitType.Percentage) { type = SvgUnitType.Percentage; value *= 100; } var element = owner as SvgElement; if (element != null) { var pattern = element.Parents.OfType <SvgPatternServer>().FirstOrDefault(); if (pattern != null && pattern.PatternContentUnits == SvgCoordinateUnits.ObjectBoundingBox && type != SvgUnitType.Percentage) { type = SvgUnitType.Percentage; value *= 100; } } float points; Font currFont; switch (type) { case SvgUnitType.Em: currFont = GetFont(renderer, owner); if (currFont == null) { points = (float)(value * 9); _deviceValue = (points / 72.0f) * ppi; } else { _deviceValue = value * (currFont.SizeInPoints / 72.0f) * ppi; } break; case SvgUnitType.Ex: currFont = GetFont(renderer, owner); if (currFont == null) { points = (float)(value * 9); _deviceValue = (points * 0.5f / 72.0f) * ppi; } else { _deviceValue = value * 0.5f * (currFont.SizeInPoints / 72.0f) * ppi; } break; case SvgUnitType.Centimeter: _deviceValue = (float)((value / cmInInch) * ppi); break; case SvgUnitType.Inch: _deviceValue = value * ppi; break; case SvgUnitType.Millimeter: _deviceValue = (float)((value / 10) / cmInInch) * ppi; break; case SvgUnitType.Pica: _deviceValue = ((value * 12) / 72) * ppi; break; case SvgUnitType.Point: _deviceValue = (value / 72) * ppi; break; case SvgUnitType.Pixel: _deviceValue = value; break; case SvgUnitType.User: _deviceValue = value; break; case SvgUnitType.Percentage: // Can't calculate if there is no style owner var boundable = (renderer == null ? (owner == null ? null : owner.OwnerDocument) : renderer.Boundable()); if (boundable == null) { _deviceValue = value; break; } System.Drawing.SizeF size = boundable.Bounds.Size; switch (renderType) { case UnitRenderingType.Horizontal: _deviceValue = (size.Width / 100) * value; break; case UnitRenderingType.HorizontalOffset: _deviceValue = (size.Width / 100) * value + boundable.Location.X; break; case UnitRenderingType.Vertical: _deviceValue = (size.Height / 100) * value; break; case UnitRenderingType.VerticalOffset: _deviceValue = (size.Height / 100) * value + boundable.Location.Y; break; default: _deviceValue = (float)(Math.Sqrt(Math.Pow(size.Width, 2) + Math.Pow(size.Height, 2)) / Math.Sqrt(2) * value / 100.0); break; } break; default: _deviceValue = value; break; } return(this._deviceValue.Value); }
private IFontDefn GetFont(ISvgRenderer renderer, SvgElement owner) { var visual = owner?.Parents.OfType <SvgVisualElement>().FirstOrDefault(); return(visual?.GetFont(renderer)); }
/// <summary> /// Initialises a new instance of a <see cref="SvgAttributeCollection"/> with the given <see cref="SvgElement"/> as the owner. /// </summary> /// <param name="owner">The <see cref="SvgElement"/> owner of the collection.</param> public SvgAttributeCollection(SvgElement owner) { this._owner = owner; }
public static System.Drawing.SizeF GetDeviceSize(SvgUnit width, SvgUnit height, ISvgRenderer renderer, SvgElement owner) { return(new System.Drawing.SizeF(width.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner), height.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner))); }
private void SetFont(SvgElement element, System.Drawing.FontFamily fontFamily) { foreach (var child in element.Children) { SetFont(child, fontFamily); //Call this function again with the child, this will loop //until the element has no more children } if (element is SvgText) { var textElement = (SvgText) element; textElement.Font = new System.Drawing.Font(fontFamily.Name, textElement.Font.Size, textElement.Font.Style, textElement.Font.Unit, textElement.Font.GdiCharSet); } }
internal static void SetPropertyValue(SvgElement element, string attributeName, string attributeValue, SvgDocument document) { var elementType = element.GetType(); PropertyInfoCollection properties; lock (syncLock) { if (!_propertyDescriptors.Keys.Contains(elementType)) { _propertyDescriptors.Add(elementType, new Dictionary <string, PropertyInfoCollection>()); } if (_propertyDescriptors[elementType].Keys.Contains(attributeName)) { properties = _propertyDescriptors[elementType][attributeName]; } else { properties = new PropertyInfoCollection(elementType);//, new[] { new SvgAttributeAttribute(attributeName) }); _propertyDescriptors[elementType].Add(attributeName, properties); } } if (properties.Count > 0) { PropertyInfo descriptor = properties[0]; try { if (attributeName == "opacity" && attributeValue == "undefined") { attributeValue = "1"; } throw new NotImplementedException(); //descriptor.SetValue(element, descriptor.Converter.ConvertFrom(document, CultureInfo.InvariantCulture, attributeValue)); } catch { //Trace.TraceWarning(string.Format("Attribute '{0}' cannot be set - type '{1}' cannot convert from string '{2}'.", attributeName, descriptor.PropertyType.FullName, attributeValue)); } } else { //check for namespace declaration in svg element if (string.Equals(element.ElementName, "svg", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(attributeName, "xmlns", StringComparison.OrdinalIgnoreCase) || string.Equals(attributeName, "xlink", StringComparison.OrdinalIgnoreCase) || string.Equals(attributeName, "xmlns:xlink", StringComparison.OrdinalIgnoreCase) || string.Equals(attributeName, "version", StringComparison.OrdinalIgnoreCase)) { //nothing to do } else { //attribute is not a svg attribute, store it in custom attributes element.CustomAttributes[attributeName] = attributeValue; } } else { //attribute is not a svg attribute, store it in custom attributes element.CustomAttributes[attributeName] = attributeValue; } } }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been added to the /// <see cref="Children"/> collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been added.</param> /// <param name="index">An <see cref="int"/> representing the index where the element was added to the collection.</param> protected virtual void AddElement(SvgElement child, int index) { }
public static System.Drawing.SizeF GetDeviceSize(SvgUnit width, SvgUnit height, ISvgRenderer renderer, SvgElement owner) { return new System.Drawing.SizeF(width.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner), height.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner)); }
protected void OnRemoved(SvgElement element) { ElementRemoved?.Invoke(this._document, new SvgElementEventArgs { Element = element }); }
private IFontDefn GetFont(ISvgRenderer renderer, SvgElement owner) { if (owner == null) return null; var visual = owner.Parents.OfType<SvgVisualElement>().FirstOrDefault(); return visual?.GetFont(renderer); }
/// <summary> /// Calls the <see cref="RemoveElement"/> method with the specified <see cref="SvgElement"/> as the parameter. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been removed.</param> internal void OnElementRemoved(SvgElement child) { this.RemoveElement(child); }
/// <summary> /// Calls the <see cref="AddElement"/> method with the specified parameters. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been added.</param> /// <param name="index">An <see cref="int"/> representing the index where the element was added to the collection.</param> internal void OnElementAdded(SvgElement child, int index) { this.AddElement(child, index); }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been added to the /// 'Children' collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been added.</param> /// <param name="index">An <see cref="int"/> representing the index where the element was added to the collection.</param> protected override void AddElement(SvgElement child, int index) { base.AddElement(child, index); IsPathDirty = true; }
private static Boolean isParent(SvgElement parent, SvgElement child) { SvgElement testIfParent = child.Parent; while (true) { if (testIfParent == null) { return false; } if (parent == testIfParent) { return true; } testIfParent = testIfParent.Parent; } }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been removed from the /// <see cref="SvgElement.Children"/> collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been removed.</param> protected override void RemoveElement(SvgElement child) { base.RemoveElement(child); IsPathDirty = true; }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been removed from the /// <see cref="Children"/> collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been removed.</param> protected override void RemoveElement(SvgElement child) { base.RemoveElement(child); this._pathDirty = true; }
public PointF ToDeviceValue(SvgRenderer renderer, SvgElement owner) { return(SvgUnit.GetDevicePoint(this.X, this.Y, renderer, owner)); }
protected void OnRemoved(SvgElement element) { var handler = ElementRemoved; if(handler != null) { handler(this._document, new SvgElementEventArgs{ Element = element }); } }
/// <summary> /// Initialises a new instance of a <see cref="SvgAttributeCollection"/> with the given <see cref="SvgElement"/> as the owner. /// </summary> /// <param name="owner">The <see cref="SvgElement"/> owner of the collection.</param> public SvgCustomAttributeCollection(SvgElement owner) { _owner = owner; }
private static T Open <T>(XmlReader reader) where T : SvgDocument, new() { var elementStack = new Stack <SvgElement>(); bool elementEmpty; SvgElement element = null; SvgElement parent; T svgDocument = null; var styles = new List <ISvgNode>(); 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) elementEmpty = reader.IsEmptyElement; // Create element if (elementStack.Count > 0) { element = SvgElementFactory.CreateElement(reader, svgDocument); } else { svgDocument = SvgElementFactory.CreateDocument <T>(reader); element = svgDocument; } // Add to the parents children if (elementStack.Count > 0) { parent = elementStack.Peek(); if (parent != null && element != null) { parent.Children.Add(element); parent.Nodes.Add(element); } } // Push element into stack elementStack.Push(element); // Need to process if the element is empty if (elementEmpty) { goto case XmlNodeType.EndElement; } break; case XmlNodeType.EndElement: // Pop the element out of the stack element = elementStack.Pop(); if (element.Nodes.OfType <SvgContentNode>().Any()) { element.Content = (from e in element.Nodes select e.Content).Aggregate((p, c) => p + c); } else { element.Nodes.Clear(); // No sense wasting the space where it isn't needed } var unknown = element as SvgUnknownElement; if (unknown != null && unknown.ElementName == "style") { styles.Add(unknown); } break; case XmlNodeType.CDATA: case XmlNodeType.Text: element = elementStack.Peek(); element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); break; case XmlNodeType.EntityReference: reader.ResolveEntity(); element = elementStack.Peek(); element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); break; } } catch (Exception exc) { Trace.TraceError(exc.Message); } } if (styles.Any()) { var cssTotal = styles.Select((s) => s.Content).Aggregate((p, c) => p + Environment.NewLine + c); var cssParser = new Parser(); var sheet = cssParser.Parse(cssTotal); AggregateSelectorList aggList; IEnumerable <BaseSelector> selectors; IEnumerable <SvgElement> elemsToStyle; foreach (var rule in sheet.StyleRules) { aggList = rule.Selector as AggregateSelectorList; if (aggList != null && aggList.Delimiter == ",") { selectors = aggList; } else { selectors = Enumerable.Repeat(rule.Selector, 1); } foreach (var selector in selectors) { elemsToStyle = svgDocument.QuerySelectorAll(rule.Selector.ToString()); foreach (var elem in elemsToStyle) { foreach (var decl in rule.Declarations) { elem.AddStyle(decl.Name, decl.Term.ToString(), rule.Selector.GetSpecificity()); } } } } } if (svgDocument != null) { FlushStyles(svgDocument); } return(svgDocument); }
public static PointF GetDevicePoint(SvgUnit x, SvgUnit y, ISvgRenderer renderer, SvgElement owner) { return(new PointF(x.ToDeviceValue(renderer, UnitRenderingType.Horizontal, owner), y.ToDeviceValue(renderer, UnitRenderingType.Vertical, owner))); }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been removed from the /// <see cref="Children"/> collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been removed.</param> protected virtual void RemoveElement(SvgElement child) { }
private static T Open <T>(XmlReader reader) where T : SvgDocument, new() { var elementStack = new Stack <SvgElement>(); bool elementEmpty; SvgElement element = null; SvgElement parent; T svgDocument = null; var elementFactory = new SvgElementFactory(); var styles = new List <ISvgNode>(); 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) elementEmpty = reader.IsEmptyElement; // Create element if (elementStack.Count > 0) { element = elementFactory.CreateElement(reader, svgDocument); } else { svgDocument = elementFactory.CreateDocument <T>(reader); element = svgDocument; } // Add to the parents children if (elementStack.Count > 0) { parent = elementStack.Peek(); if (parent != null && element != null) { parent.Children.Add(element); parent.Nodes.Add(element); } } // Push element into stack elementStack.Push(element); // Need to process if the element is empty if (elementEmpty) { goto case XmlNodeType.EndElement; } break; case XmlNodeType.EndElement: // Pop the element out of the stack element = elementStack.Pop(); if (element.Nodes.OfType <SvgContentNode>().Any()) { element.Content = (from e in element.Nodes select e.Content).Aggregate((p, c) => p + c); } else { element.Nodes.Clear(); // No sense wasting the space where it isn't needed } var unknown = element as SvgUnknownElement; if (unknown != null && unknown.ElementName == "style") { styles.Add(unknown); } break; case XmlNodeType.CDATA: case XmlNodeType.Text: element = elementStack.Peek(); element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); break; case XmlNodeType.EntityReference: reader.ResolveEntity(); element = elementStack.Peek(); element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); break; } } catch (Exception exc) { Trace.TraceError(exc.Message); } } return(svgDocument); }