Expression CreateStroke(string stroke, string strokeWidth, string opacity, SvgRendererContext context) { Expression colorArgument; if (stroke == null || stroke == "none") { return(null); } var alpha = opacity == null ? null : (int?)(((SvgLength)opacity).Value * 255); if (stroke == "currentColor") { colorArgument = Expression.PropertyOrField(context.State, "CurrentColor"); if (alpha.HasValue) { var alphaArgument = Expression.Constant(alpha.Value); colorArgument = Expression.Call(typeof(Color), "FromArgb", null, alphaArgument, colorArgument); } } else { var color = ((SvgColor)stroke).Color; if (alpha.HasValue) { color = Color.FromArgb(alpha.Value, color); } colorArgument = Expression.Constant(color); } var width = strokeWidth == null ? 1 : ((SvgLength)strokeWidth); var widthArgument = Expression.Constant(width.Value); return(Expression.Call(context.State, "StrokeStyle", null, colorArgument, widthArgument)); }
void CreateDrawChildren(SvgElement element, Matrix transform, SvgRendererContext context) { foreach (SvgElement child in element.Children) { CreateDrawBody(child, transform, context); } }
void CreateDrawEllipse(SvgElement element, Matrix transform, SvgRendererContext context) { var style = CreateStyle(element, context); if (style != null) { var cx = ParseFloat(element, "cx"); var cy = ParseFloat(element, "cy"); var rx = ParseFloat(element, "rx"); var ry = ParseFloat(element, "ry"); var x = Expression.Constant(cx - rx); var y = Expression.Constant(cy - ry); var dx = Expression.Constant(2f * rx); var dy = Expression.Constant(2f * ry); CreateDrawTransform(element, transform, context); if (style.Fill != null) { context.Expressions.Add(Expression.Call(context.Graphics, "FillEllipse", null, style.Fill, x, y, dx, dy)); } if (style.Stroke != null) { context.Expressions.Add(Expression.Call(context.Graphics, "DrawEllipse", null, style.Stroke, x, y, dx, dy)); } CreateResetTransform(context); } }
SvgRenderer CreateRenderer(SvgElement element) { var context = new SvgRendererContext(); CreateDrawBody(element, null, context); var body = context.Expressions.Count > 0 ? (Expression)Expression.Block(context.Expressions) : Expression.Empty(); var renderer = Expression.Lambda <SvgRenderer>(body, context.State, context.Graphics); return(renderer.Compile()); }
Expression CreateFill(SvgStyle style, SvgRendererContext context) { if (style == null) { return(CreateFill(null, null, context)); } var fill = (string)style.Get("fill"); var opacity = (string)style.Get("fill-opacity"); return(CreateFill(fill, opacity, context)); }
void CreateDrawDefinitions(SvgElement element, SvgRendererContext context) { foreach (SvgElement child in element.Children) { switch (child.Name) { case "linearGradient": CreateLinearGradient(child, context); break; default: continue; } } }
Expression CreateStroke(SvgStyle style, SvgRendererContext context) { if (style == null) { return(null); } var stroke = (string)style.Get("stroke"); var strokeWidth = (string)style.Get("stroke-width"); var strokeOpacity = (string)style.Get("stroke-opacity"); return(CreateStroke(stroke, strokeWidth, strokeOpacity, context)); }
void CreateDrawTransform(SvgElement element, Matrix transform, SvgRendererContext context) { var localTransform = CreateTransform(element, transform); var scale = Expression.PropertyOrField(context.State, "Scale"); var translation = Expression.PropertyOrField(context.State, "Translation"); var offsetX = Expression.PropertyOrField(translation, "X"); var offsetY = Expression.PropertyOrField(translation, "Y"); context.Expressions.Add(Expression.Call(context.Graphics, "TranslateTransform", null, offsetX, offsetY)); context.Expressions.Add(Expression.Call(context.Graphics, "ScaleTransform", null, scale, scale)); if (localTransform != null) { context.Expressions.Add(Expression.Call(context.Graphics, "MultiplyTransform", null, localTransform)); } }
SvgDrawingStyle CreateStyle(SvgElement element, SvgRendererContext context) { Expression fill, stroke; var style = GetElementStyle(element); fill = CreateFill(style, context); stroke = CreateStroke(style, context); if (fill == null && stroke == null) { return(null); } else { return(new SvgDrawingStyle(fill, stroke)); } }
void CreateLinearGradient(SvgElement element, SvgRendererContext context) { var linearGradient = element as SvgLinearGradientElement; if (linearGradient != null) { var color1 = default(Color); var color2 = default(Color); LinearGradientBrush gradient; if (linearGradient.Children.Count == 2) { var stop1 = linearGradient.Children[0] as SvgStopElement; var stop2 = linearGradient.Children[1] as SvgStopElement; if (stop1 != null && stop2 != null) { color1 = ParseStopColor(stop1); color2 = ParseStopColor(stop2); } } else { Brush referenceGradient; LinearGradientBrush referenceLinearGradient; var href = new SvgXRef(linearGradient).Href; if (href != null && context.Gradients.TryGetValue(href, out referenceGradient) && (referenceLinearGradient = referenceGradient as LinearGradientBrush) != null) { color1 = referenceLinearGradient.LinearColors[0]; color2 = referenceLinearGradient.LinearColors[1]; } } var gradientTransform = ParseTransform(linearGradient, null, "gradientTransform"); var points = new[] { ParsePoint(linearGradient, "x1", "y1").GetValueOrDefault(PointF.Empty), ParsePoint(linearGradient, "x2", "y2").GetValueOrDefault(new PointF(1, 1)) }; if (gradientTransform != null) { gradientTransform.TransformPoints(points); } gradient = new LinearGradientBrush(points[0], points[1], color1, color2); context.Gradients.Add(new SvgUriReference(linearGradient).Href, gradient); disposableResources.Add(gradient); } }
void CreateDrawPath(SvgElement element, Matrix transform, SvgRendererContext context) { var style = CreateStyle(element, context); if (style != null) { var path = CreatePath(element, "d"); CreateDrawTransform(element, transform, context); if (style.Fill != null) { context.Expressions.Add(Expression.Call(context.Graphics, "FillPath", null, style.Fill, path)); } if (style.Stroke != null) { context.Expressions.Add(Expression.Call(context.Graphics, "DrawPath", null, style.Stroke, path)); } CreateResetTransform(context); } }
void CreateDrawBody(SvgElement element, Matrix transform, SvgRendererContext context) { switch (element.Name) { case "rect": CreateDrawRectangle(element, transform, context); break; case "circle": CreateDrawCircle(element, transform, context); break; case "ellipse": CreateDrawEllipse(element, transform, context); break; case "path": CreateDrawPath(element, transform, context); break; case "svg": CreateDrawChildren(element, transform, context); break; case "defs": CreateDrawDefinitions(element, context); break; case "g": var localTransform = ParseTransform(element, transform); CreateDrawChildren(element, localTransform, context); break; } }
void CreateDrawRectangle(SvgElement element, Matrix transform, SvgRendererContext context) { var style = CreateStyle(element, context); if (style != null) { var x = CreateFloat(element, "x"); var y = CreateFloat(element, "y"); var width = CreateFloat(element, "width"); var height = CreateFloat(element, "height"); CreateDrawTransform(element, transform, context); if (style.Fill != null) { context.Expressions.Add(Expression.Call(context.Graphics, "FillRectangle", null, style.Fill, x, y, width, height)); } if (style.Stroke != null) { context.Expressions.Add(Expression.Call(context.Graphics, "DrawRectangle", null, style.Stroke, x, y, width, height)); } CreateResetTransform(context); } }
Expression CreateFill(string fill, string opacity, SvgRendererContext context) { const string UrlPrefix = "url("; if (fill == "none") { return(null); } if (fill == null) { return(Expression.Call(context.State, "FillStyle", null)); } if (fill.StartsWith(UrlPrefix)) { Brush brush; var href = fill.Substring(UrlPrefix.Length, fill.Length - UrlPrefix.Length - 1); if (!context.Gradients.TryGetValue(href, out brush)) { return(null); } else { return(Expression.Constant(brush)); } } else { var color = ((SvgColor)fill).Color; if (opacity != null) { var opacityValue = ((SvgLength)opacity).Value; color = Color.FromArgb((int)(opacityValue * 255), color); } return(Expression.Call(context.State, "FillStyle", null, Expression.Constant(color))); } }
void CreateResetTransform(SvgRendererContext context) { context.Expressions.Add(Expression.Call(context.Graphics, "ResetTransform", null)); }