public void DrawRoundRect(float x, float y, float w, float h, float rx, float ry, SKPaint paint) { DrawRoundRect(SKRect.Create(x, y, w, h), rx, ry, paint); }
public void DrawRect(float x, float y, float w, float h, SKPaint paint) { DrawRect(SKRect.Create(x, y, w, h), paint); }
public static void ColorMatrixColorFilter(SKCanvas canvas, int width, int height) { canvas.Clear(SKColors.White); var assembly = typeof(Demos).GetTypeInfo().Assembly; var imageName = assembly.GetName().Name + ".baboon.png"; // load the image from the embedded resource stream using (var resource = assembly.GetManifestResourceStream(imageName)) using (var stream = new SKManagedStream(resource)) using (var bitmap = SKBitmap.Decode(stream)) { var f = new Action <SKRect, float[]>((rect, colorMatrix) => { using (var cf = SKColorFilter.CreateColorMatrix(colorMatrix)) using (var paint = new SKPaint()) { paint.ColorFilter = cf; canvas.DrawBitmap(bitmap, rect, paint); } }); var colorMatrix1 = new float[20] { 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 1f, 0f }; var grayscale = new float[20] { 0.21f, 0.72f, 0.07f, 0.0f, 0.0f, 0.21f, 0.72f, 0.07f, 0.0f, 0.0f, 0.21f, 0.72f, 0.07f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; var colorMatrix3 = new float[20] { -1f, 1f, 1f, 0f, 0f, 1f, -1f, 1f, 0f, 0f, 1f, 1f, -1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f }; var colorMatrix4 = new float[20] { 0.0f, 0.5f, 0.5f, 0f, 0f, 0.5f, 0.0f, 0.5f, 0f, 0f, 0.5f, 0.5f, 0.0f, 0f, 0f, 0.0f, 0.0f, 0.0f, 1f, 0f }; var highContrast = new float[20] { 4.0f, 0.0f, 0.0f, 0.0f, -4.0f * 255f / (4.0f - 1f), 0.0f, 4.0f, 0.0f, 0.0f, -4.0f * 255f / (4.0f - 1f), 0.0f, 0.0f, 4.0f, 0.0f, -4.0f * 255f / (4.0f - 1f), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; var colorMatrix6 = new float[20] { 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 0f, 1f, 0f }; var sepia = new float[20] { 0.393f, 0.769f, 0.189f, 0.0f, 0.0f, 0.349f, 0.686f, 0.168f, 0.0f, 0.0f, 0.272f, 0.534f, 0.131f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; var inverter = new float[20] { -1f, 0f, 0f, 0f, 255f, 0f, -1f, 0f, 0f, 255f, 0f, 0f, -1f, 0f, 255f, 0f, 0f, 0f, 1f, 0f }; var matices = new[] { colorMatrix1, grayscale, highContrast, sepia, colorMatrix3, colorMatrix4, colorMatrix6, inverter }; var cols = width < height ? 2 : 4; var rows = (matices.Length - 1) / cols + 1; var w = (float)width / cols; var h = (float)height / rows; for (int y = 0; y < rows; y++) { for (int x = 0; x < cols; x++) { f(SKRect.Create(x * w, y * h, w, h), matices[y * cols + x]); } } } }
public static void Xfermode(SKCanvas canvas, int width, int height) { var modes = Enum.GetValues(typeof(SKXferMode)).Cast <SKXferMode> ().ToArray(); var cols = width < height ? 3 : 5; var rows = (modes.Length - 1) / cols + 1; var w = (float)width / cols; var h = (float)height / rows; var rect = SKRect.Create(w, h); var srcPoints = new[] { new SKPoint(0.0f, 0.0f), new SKPoint(w, 0.0f) }; var srcColors = new [] { SKColors.Magenta.WithAlpha(0), SKColors.Magenta }; var dstPoints = new [] { new SKPoint(0.0f, 0.0f), new SKPoint(0.0f, h) }; var dstColors = new [] { SKColors.Cyan.WithAlpha(0), SKColors.Cyan }; using (var text = new SKPaint()) using (var stroke = new SKPaint()) using (var src = new SKPaint()) using (var dst = new SKPaint()) using (var srcShader = SKShader.CreateLinearGradient(srcPoints [0], srcPoints [1], srcColors, null, SKShaderTileMode.Clamp)) using (var dstShader = SKShader.CreateLinearGradient(dstPoints [0], dstPoints [1], dstColors, null, SKShaderTileMode.Clamp)) { text.TextSize = 12.0f; text.IsAntialias = true; text.TextAlign = SKTextAlign.Center; stroke.IsStroke = true; src.Shader = srcShader; dst.Shader = dstShader; canvas.Clear(SKColors.White); for (var i = 0; i < modes.Length; ++i) { using (new SKAutoCanvasRestore(canvas, true)) { canvas.Translate(w * (i / rows), h * (i % rows)); canvas.ClipRect(rect); canvas.DrawColor(SKColors.LightGray); canvas.SaveLayer(null); canvas.Clear(SKColors.Transparent); canvas.DrawPaint(dst); src.XferMode = modes [i]; canvas.DrawPaint(src); canvas.DrawRect(rect, stroke); var desc = modes [i].ToString(); canvas.DrawText(desc, w / 2f, h / 2f, text); } } } }
private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill) { // transform matrix var transform = ReadTransform(e.Attribute("transform")?.Value ?? string.Empty); canvas.Save(); canvas.Concat(ref transform); // SVG element var elementName = e.Name.LocalName; var isGroup = elementName == "g"; // read style var style = ReadPaints(e, ref stroke, ref fill, isGroup); // parse elements switch (elementName) { case "text": if (stroke != null || fill != null) { ReadText(e, canvas, stroke?.Clone(), fill?.Clone()); } break; case "rect": if (stroke != null || fill != null) { var x = ReadNumber(e.Attribute("x")); var y = ReadNumber(e.Attribute("y")); var width = ReadNumber(e.Attribute("width")); var height = ReadNumber(e.Attribute("height")); var rx = ReadNumber(e.Attribute("rx")); var ry = ReadNumber(e.Attribute("ry")); var rect = SKRect.Create(x, y, width, height); if (rx > 0 || ry > 0) { if (fill != null) { canvas.DrawRoundRect(rect, rx, ry, fill); } if (stroke != null) { canvas.DrawRoundRect(rect, rx, ry, stroke); } } else { if (fill != null) { canvas.DrawRect(rect, fill); } if (stroke != null) { canvas.DrawRect(rect, stroke); } } } break; case "ellipse": if (stroke != null || fill != null) { var cx = ReadNumber(e.Attribute("cx")); var cy = ReadNumber(e.Attribute("cy")); var rx = ReadNumber(e.Attribute("rx")); var ry = ReadNumber(e.Attribute("ry")); if (fill != null) { canvas.DrawOval(cx, cy, rx, ry, fill); } if (stroke != null) { canvas.DrawOval(cx, cy, rx, ry, stroke); } } break; case "circle": if (stroke != null || fill != null) { var cx = ReadNumber(e.Attribute("cx")); var cy = ReadNumber(e.Attribute("cy")); var rr = ReadNumber(e.Attribute("r")); if (fill != null) { canvas.DrawCircle(cx, cy, rr, fill); } if (stroke != null) { canvas.DrawCircle(cx, cy, rr, stroke); } } break; case "path": if (stroke != null || fill != null) { var d = e.Attribute("d")?.Value; if (!string.IsNullOrWhiteSpace(d)) { var path = SKPath.ParseSvgPathData(d); if (fill != null) { canvas.DrawPath(path, fill); } if (stroke != null) { canvas.DrawPath(path, stroke); } } } break; case "polygon": case "polyline": if (stroke != null || fill != null) { var close = elementName == "polygon"; var p = e.Attribute("points")?.Value; if (!string.IsNullOrWhiteSpace(p)) { var path = ReadPolyPath(p, close); if (fill != null) { canvas.DrawPath(path, fill); } if (stroke != null) { canvas.DrawPath(path, stroke); } } } break; case "g": if (e.HasElements) { // get current group opacity float groupOpacity = ReadOpacity(style); if (groupOpacity != 1.0f) { var opacity = (byte)(255 * groupOpacity); var opacityPaint = new SKPaint { Color = SKColors.Black.WithAlpha(opacity) }; // apply the opacity canvas.SaveLayer(opacityPaint); } foreach (var gElement in e.Elements()) { ReadElement(gElement, canvas, stroke?.Clone(), fill?.Clone()); } // restore state if (groupOpacity != 1.0f) { canvas.Restore(); } } break; case "use": if (e.HasAttributes) { var href = ReadHref(e); if (href != null) { // TODO: copy/process other attributes var x = ReadNumber(e.Attribute("x")); var y = ReadNumber(e.Attribute("y")); var useTransform = SKMatrix.MakeTranslation(x, y); canvas.Save(); canvas.Concat(ref useTransform); ReadElement(href, canvas, stroke?.Clone(), fill?.Clone()); canvas.Restore(); } } break; case "line": if (stroke != null) { var x1 = ReadNumber(e.Attribute("x1")); var x2 = ReadNumber(e.Attribute("x2")); var y1 = ReadNumber(e.Attribute("y1")); var y2 = ReadNumber(e.Attribute("y2")); canvas.DrawLine(x1, y1, x2, y2, stroke); } break; case "switch": if (e.HasElements) { foreach (var ee in e.Elements()) { var requiredFeatures = ee.Attribute("requiredFeatures"); var requiredExtensions = ee.Attribute("requiredExtensions"); var systemLanguage = ee.Attribute("systemLanguage"); // TODO: evaluate requiredFeatures, requiredExtensions and systemLanguage var isVisible = requiredFeatures == null && requiredExtensions == null && systemLanguage == null; if (isVisible) { ReadElement(ee, canvas, stroke?.Clone(), fill?.Clone()); } } } break; case "defs": case "title": case "desc": case "description": // already read earlier break; default: LogOrThrow($"SVG element '{elementName}' is not supported"); break; } // restore matrix canvas.Restore(); }
private SKPicture Load(XDocument xdoc) { var svg = xdoc.Root; var ns = svg.Name.Namespace; // find the defs (gradients) - and follow all hrefs foreach (var d in svg.Descendants()) { var id = d.Attribute("id")?.Value?.Trim(); if (!string.IsNullOrEmpty(id)) { defs[id] = ReadDefinition(d); } } Version = svg.Attribute("version")?.Value; Title = svg.Element(ns + "title")?.Value; Description = svg.Element(ns + "desc")?.Value ?? svg.Element(ns + "description")?.Value; // TODO: parse the "preserveAspectRatio" values properly var preserveAspectRatio = svg.Attribute("preserveAspectRatio")?.Value; // get the SVG dimensions var viewBoxA = svg.Attribute("viewBox") ?? svg.Attribute("viewPort"); if (viewBoxA != null) { ViewBox = ReadRectangle(viewBoxA.Value); } if (CanvasSize.IsEmpty) { // get the user dimensions var widthA = svg.Attribute("width"); var heightA = svg.Attribute("height"); var width = ReadNumber(widthA); var height = ReadNumber(heightA); var size = new SKSize(width, height); if (widthA == null) { size.Width = ViewBox.Width; } else if (widthA.Value.Contains("%")) { size.Width *= ViewBox.Width; } if (heightA == null) { size.Height = ViewBox.Height; } else if (heightA != null && heightA.Value.Contains("%")) { size.Height *= ViewBox.Height; } // set the property CanvasSize = size; } // create the picture from the elements using (var recorder = new SKPictureRecorder()) using (var canvas = recorder.BeginRecording(SKRect.Create(CanvasSize))) { // if there is no viewbox, then we don't do anything, otherwise // scale the SVG dimensions to fit inside the user dimensions if (!ViewBox.IsEmpty && (ViewBox.Width != CanvasSize.Width || ViewBox.Height != CanvasSize.Height)) { if (preserveAspectRatio == "none") { canvas.Scale(CanvasSize.Width / ViewBox.Width, CanvasSize.Height / ViewBox.Height); } else { // TODO: just center scale for now var scale = Math.Min(CanvasSize.Width / ViewBox.Width, CanvasSize.Height / ViewBox.Height); var centered = SKRect.Create(CanvasSize).AspectFit(ViewBox.Size); canvas.Translate(centered.Left, centered.Top); canvas.Scale(scale, scale); } } // translate the canvas by the viewBox origin canvas.Translate(-ViewBox.Left, -ViewBox.Top); // if the viewbox was specified, then crop to that if (!ViewBox.IsEmpty) { canvas.ClipRect(ViewBox); } LoadElements(svg.Elements(), canvas); Picture = recorder.EndRecording(); } return(Picture); }
public static SKRect Margin(this SKRect rect, int value) { return(SKRect.Create(rect.Left - value, rect.Top - value, rect.Width + value * 2, rect.Height + value * 2)); }