public override IEnumerable <SvgAttribute> GetAttributes() { var baseAttributes = base.GetAttributes(); if (baseAttributes != null) { foreach (var attr in baseAttributes) { yield return(attr); } } var ci = CultureInfo.InvariantCulture; yield return(new SvgAttribute("x1", "0", () => X1.ToString(ci), v => X1 = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("y1", "0", () => Y1.ToString(ci), v => Y1 = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("x2", "0", () => X2.ToString(ci), v => X2 = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("y2", "0", () => Y2.ToString(ci), v => Y2 = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("stroke-width", () => StrokeWidth.ToString(ci), v => StrokeWidth = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("stroke", () => Stroke == Color.Empty ? "none" : ColorTranslator.ToSvg(Stroke), v => Stroke = SvgAttribute.ParseColorAttribute(v, Stroke.A) )); yield return(new SvgAttribute("stroke-opacity", "1", () => ((double)Stroke.A / 255).ToString(ci), v => Stroke = SvgAttribute.ParseOpacityAttribute(v, Stroke) )); yield return(new SvgAttribute("stroke-dashoffset", () => StrokeDashOffset.ToString(ci), v => StrokeDashOffset = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("stroke-dasharray", () => DashArrayToString(), v => StrokeDashArray = SvgAttribute.ParseFloatArray(v) )); }
public override IEnumerable <SvgAttribute> GetAttributes() { var baseAttributes = base.GetAttributes(); if (baseAttributes != null) { foreach (var attr in baseAttributes) { yield return(attr); } } var ci = CultureInfo.InvariantCulture; yield return(new SvgAttribute("cx", "0", () => Cx.ToString(ci), v => Cx = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("cy", "0", () => Cy.ToString(ci), v => Cy = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("rx", "0", () => Rx.ToString(ci), v => Rx = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("ry", "0", () => Ry.ToString(ci), v => Ry = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("stroke-width", () => StrokeWidth.ToString(ci), v => StrokeWidth = SvgAttribute.ParseFloatAttribute(v) )); yield return(new SvgAttribute("stroke", () => ColorTranslator.ToSvg(Stroke), v => Stroke = SvgAttribute.ParseColorAttribute(v, Stroke.A) )); yield return(new SvgAttribute("stroke-opacity", "1", () => ((double)Stroke.A / 255).ToString(ci), v => Stroke = SvgAttribute.ParseOpacityAttribute(v, Stroke) )); yield return(new SvgAttribute("fill", () => Fill.A == 0 ? "none" : ColorTranslator.ToSvg(Fill), v => Fill = SvgAttribute.ParseColorAttribute(v, Fill.A) )); yield return(new SvgAttribute("fill-opacity", "1", () => ((double)Fill.A / 255).ToString(ci), v => Fill = SvgAttribute.ParseOpacityAttribute(v, Fill) )); }
public override int GetHashCode() { return(string.Concat(FillColor.ToString(), StrokeColor.ToString(), StrokeWidth.GetHashCode()).GetHashCode()); //return ComputeStringHash(FillColor, StrokeColor, StrokeWidth); //unchecked //{ // int hash = FillColor.ToString().GetHashCode(); // // Maybe nullity checks, if these are objects not primitives! // hash = hash * 29 + StrokeColor.ToString().GetHashCode(); // hash = hash * 29 + StrokeWidth.ToString().GetHashCode(); // return hash; //} }
/// <summary> /// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="ISvgRenderer"/> /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> /// <param name="stroke"></param> protected internal virtual bool RenderStroke(ISvgRenderer renderer, SvgPaintServer stroke = null) { stroke = stroke ?? Stroke; if (stroke != null && stroke != SvgPaintServer.None) { var strokeWidth = StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this); renderer.DrawPath(Path(renderer), stroke.GetColor(this, renderer, FixOpacityValue(StrokeOpacity), true), strokeWidth); return(true); } return(false); }
/// <summary> /// Create a pen that can be used to render this marker /// </summary> /// <param name="pStroke"></param> /// <returns></returns> private Pen CreatePen(SvgPath pPath, SvgRenderer renderer) { Brush pBrush = pPath.Stroke.GetBrush(this, renderer, Opacity); switch (MarkerUnits) { case SvgMarkerUnits.strokeWidth: return(new Pen(pBrush, StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this) * pPath.StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); case SvgMarkerUnits.userSpaceOnUse: return(new Pen(pBrush, StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); } return(new Pen(pBrush, StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); }
/// <summary> /// Create a pen that can be used to render this marker /// </summary> /// <returns></returns> private Pen CreatePen(SvgVisualElement pPath, ISvgRenderer renderer) { if (pPath.Stroke == null) { return(null); } Brush pBrush = pPath.Stroke.GetBrush(this, renderer, Opacity); switch (MarkerUnits) { case SvgMarkerUnits.StrokeWidth: return(new Pen(pBrush, StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this) * pPath.StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); case SvgMarkerUnits.UserSpaceOnUse: return(new Pen(pBrush, StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); } return(new Pen(pBrush, StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); }
/// <summary> /// Create a pen that can be used to render this marker /// </summary> /// <returns></returns> private Pen CreatePen(SvgVisualElement pPath, ISvgRenderer renderer) { if (this.Stroke == null) { return(null); } Brush pBrush = this.Stroke.GetBrush(this, renderer, FixOpacityValue(Opacity)); switch (MarkerUnits) { case SvgMarkerUnits.StrokeWidth: // TODO: have to multiply with marker stroke width if it is not inherted from the // same ancestor as owner path stroke width return(new Pen(pBrush, pPath.StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); case SvgMarkerUnits.UserSpaceOnUse: return(new Pen(pBrush, StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); } return(new Pen(pBrush, StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this))); }
/// <summary> /// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="ISvgRenderer"/> /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> protected internal virtual bool RenderStroke(ISvgRenderer renderer) { if (Stroke != null && Stroke != SvgPaintServer.None && StrokeWidth > 0f) { var strokeWidth = StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this); using (var brush = Stroke.GetBrush(this, renderer, Math.Min(Math.Max(StrokeOpacity, 0f), 1f), true)) { if (brush != null) { var path = Path(renderer); var bounds = path.GetBounds(); if (path.PointCount < 1) { return(false); } if (bounds.Width <= 0f && bounds.Height <= 0f) { switch (StrokeLineCap) { case SvgStrokeLineCap.Round: using (var capPath = new GraphicsPath()) { capPath.AddEllipse(path.PathPoints[0].X - strokeWidth / 2f, path.PathPoints[0].Y - strokeWidth / 2f, strokeWidth, strokeWidth); renderer.FillPath(brush, capPath); } break; case SvgStrokeLineCap.Square: using (var capPath = new GraphicsPath()) { capPath.AddRectangle(new RectangleF(path.PathPoints[0].X - strokeWidth / 2f, path.PathPoints[0].Y - strokeWidth / 2f, strokeWidth, strokeWidth)); renderer.FillPath(brush, capPath); } break; } } else { using (var pen = new Pen(brush, strokeWidth)) { if (StrokeDashArray != null && StrokeDashArray.Count > 0) { strokeWidth = strokeWidth <= 0 ? 1f : strokeWidth; if (StrokeDashArray.Count % 2 != 0) { // handle odd dash arrays by repeating them once StrokeDashArray.AddRange(StrokeDashArray); } var dashOffset = StrokeDashOffset; /* divide by stroke width - GDI uses stroke width as unit.*/ var dashPattern = StrokeDashArray.Select(u => ((u.ToDeviceValue(renderer, UnitRenderingType.Other, this) <= 0f) ? 1f : u.ToDeviceValue(renderer, UnitRenderingType.Other, this)) / strokeWidth).ToArray(); var length = dashPattern.Length; if (StrokeLineCap == SvgStrokeLineCap.Round) { // to handle round caps, we have to adapt the dash pattern // by increasing the dash length by the stroke width - GDI draws the rounded // edge inside the dash line, SVG draws it outside the line var pattern = new float[length]; var offset = 1; // the values are already normalized to dash width for (var i = 0; i < length; i++) { pattern[i] = dashPattern[i] + offset; if (pattern[i] <= 0f) { // overlapping caps - remove the gap for simplicity, see #508 if (i < length - 1) { // add the next dash segment to the current one dashPattern[i - 1] += dashPattern[i] + dashPattern[i + 1]; length -= 2; for (var k = i; k < length; k++) { dashPattern[k] = dashPattern[k + 2]; } // and handle the combined segment again i -= 2; } else if (i > 2) { // add the last dash segment to the first one // this will change the start point, so adapt the offset var dashLength = dashPattern[i - 1] + dashPattern[i]; pattern[0] += dashLength; length -= 2; dashOffset += dashLength * strokeWidth; } else { // we have only one dash with the gap too small - // do not use dash at all length = 0; break; } } offset *= -1; // increase dash length, decrease spaces } if (length > 0) { if (length < dashPattern.Length) { Array.Resize(ref pattern, length); } dashPattern = pattern; pen.DashCap = DashCap.Round; } } if (length > 0) { pen.DashPattern = dashPattern; if (dashOffset != 0f) { pen.DashOffset = ((dashOffset.ToDeviceValue(renderer, UnitRenderingType.Other, this) <= 0f) ? 1f : dashOffset.ToDeviceValue(renderer, UnitRenderingType.Other, this)) / strokeWidth; } } } switch (StrokeLineJoin) { case SvgStrokeLineJoin.Bevel: pen.LineJoin = LineJoin.Bevel; break; case SvgStrokeLineJoin.Round: pen.LineJoin = LineJoin.Round; break; default: pen.LineJoin = LineJoin.Miter; break; } pen.MiterLimit = StrokeMiterLimit; switch (StrokeLineCap) { case SvgStrokeLineCap.Round: pen.StartCap = LineCap.Round; pen.EndCap = LineCap.Round; break; case SvgStrokeLineCap.Square: pen.StartCap = LineCap.Square; pen.EndCap = LineCap.Square; break; } renderer.DrawPath(pen, path); return(true); } } } } } return(false); }
public override int GetHashCode() { return(StrokeWidth.GetHashCode() ^ Color.GetHashCode()); }