/// <summary> /// performs a translation transform on the diagram in order to push it to the "top-left" corner of the diagram. /// TODO: might make sense if the scale transform ends up using this as well. /// </summary> /// <param name="state"></param> /// <param name="diagram"></param> /// <returns></returns> private static IDiagram NormalizeToTopLeftCorner(SvgDrawState state, IDiagram diagram) { var vector = Vector.FromCoordinates( diagram.Bounds.TopLeft, state.Converter.BoundingBox.TopLeft ); //TODO: once implemented, should this use the more "programmatic" offset approach? (that doesn't rely on the SVG transform?) return(diagram.WithOffset(vector)); }
public static State <SvgDrawState, IEnumerable <XAttribute> > GenerateStyleAttributes(IStyleProperty styleProperty) { if (styleProperty is FillProperty fillProperty) { return(new[] { new XAttribute("fill", SvgColor(fillProperty.FillColor)), new XAttribute("fill-opacity", SvgOpacity(fillProperty.FillColor)), } .Pipe(State.Return <SvgDrawState, IEnumerable <XAttribute> >)); } if (styleProperty is GradientFillProperty gradientFillProperty) { var gradientState = State.Return <SvgDrawState, XElementBuilder>(() => BuildGradientElement(gradientFillProperty.Gradient)); return (from id in SvgDrawState.IncludeDefinition(gradientFillProperty.Gradient, gradientState) select new[] { new XAttribute("fill", $"url(#{id})") }.AsEnumerable()); } if (styleProperty is FillPatternProperty fillPatternProperty) { var patternFactory = RenderPattern(fillPatternProperty.PatternDiagram, fillPatternProperty.FillWidthRatio, fillPatternProperty.FillHeightRatio); return (from id in SvgDrawState.IncludeDefinition(fillPatternProperty, patternFactory) select new[] { new XAttribute("fill", $"url(#{id})") }.AsEnumerable()); } if (styleProperty is FilterProperty filterProperty) { var filterFactory = from drawState in State.Get <SvgDrawState>() select SvgFilterFactory.BuildFilter(filterProperty.FilterComponent, drawState.Converter); return (from id in SvgDrawState.IncludeDefinition(filterProperty, filterFactory) select new[] { new XAttribute("filter", $"url(#{id})") }.AsEnumerable()); } if (styleProperty is StrokeColorProperty strokeColorProperty) { return (new[] { new XAttribute("stroke", SvgColor(strokeColorProperty.Color)), new XAttribute("stroke-opacity", SvgOpacity(strokeColorProperty.Color)) } .AsEnumerable() .Pipe(State.Return <SvgDrawState, IEnumerable <XAttribute> >)); } if (styleProperty is StrokeWidthProperty strokeWidthProperty) { return (from state in State.Get <SvgDrawState>() let svgStrokeWidth = CalculateStrokeWidth(strokeWidthProperty.StrokeWidth, state.Converter) select new[] { new XAttribute("stroke-width", svgStrokeWidth) }.AsEnumerable()); } throw new Exception($"unable to render fill type of style property {styleProperty.GetType()}"); }