public static SKPaint ScaledPaint(float scale, SKPaint paint)
        {
            var cpy = paint.Clone();

            cpy.TextSize *= scale;
            return(cpy);
        }
예제 #2
0
파일: RICanvas.cs 프로젝트: emmauss/Ngco
 SKPaint ScalePaint(SKPaint paint)
 {
     paint              = paint.Clone();
     paint.TextSize    *= Scale;
     paint.StrokeWidth *= Scale;
     return(paint);
 }
예제 #3
0
 private void LoadElements(IEnumerable <XElement> elements, SKCanvas canvas, SKPaint stroke, SKPaint fill)
 {
     foreach (var e in elements)
     {
         ReadElement(e, canvas, stroke?.Clone(), fill?.Clone());
     }
 }
예제 #4
0
 public Brush Clone()
 {
     return(new SolidBrush()
     {
         nativeBrush = nativeBrush?.Clone()
     });
 }
예제 #5
0
		public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, float x, float y, SKPaint paint)
		{
			if (canvas == null)
				throw new ArgumentNullException(nameof(canvas));
			if (shaper == null)
				throw new ArgumentNullException(nameof(shaper));
			if (text == null)
				throw new ArgumentNullException(nameof(text));
			if (paint == null)
				throw new ArgumentNullException(nameof(paint));

			if (string.IsNullOrEmpty(text))
				return;

			// shape the text
			var result = shaper.Shape(text, x, y, paint);

			// draw the text

			using (var paintClone = paint.Clone())
			{
				paintClone.TextEncoding = SKTextEncoding.GlyphId;
				paintClone.Typeface = shaper.Typeface;

				var bytes = result.Codepoints.Select(cp => BitConverter.GetBytes((ushort)cp)).SelectMany(b => b).ToArray();
				canvas.DrawPositionedText(bytes, result.Points, paintClone);
			}
		}
예제 #6
0
        void OnTouchEffectAction(object sender, TouchActionEventArgs args)
        {
            try
            {
                switch (args.Type)
                {
                case TouchActionType.Pressed:
                    Debug.WriteLine(args.Id);
                    if (!inProgressPaths.ContainsKey(args.Id))
                    {
                        SKPath path = new SKPath();
                        path.MoveTo(ConvertToPixel(args.Location));
                        try
                        {
                            inProgressPaths.TryAdd(args.Id, path);
                        }
                        catch (Exception e)
                        {
                            Debug.WriteLine(e);
                        }
                        canvasView.InvalidateSurface();
                    }
                    break;

                case TouchActionType.Moved:
                    if (inProgressPaths.ContainsKey(args.Id))
                    {
                        SKPath path = inProgressPaths[args.Id];
                        path.LineTo(ConvertToPixel(args.Location));
                        canvasView.InvalidateSurface();
                    }
                    break;

                case TouchActionType.Released:
                    if (inProgressPaths.ContainsKey(args.Id))
                    {
                        completedPaths.Add(new PaintPath()
                        {
                            Path = inProgressPaths[args.Id], Paint = paint.Clone()
                        });
                        inProgressPaths.TryRemove(args.Id, out _);
                        canvasView.InvalidateSurface();
                    }
                    break;

                case TouchActionType.Cancelled:
                    if (inProgressPaths.ContainsKey(args.Id))
                    {
                        inProgressPaths.TryRemove(args.Id, out _);
                        canvasView.InvalidateSurface();
                    }
                    break;
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
        }
예제 #7
0
        private GridPaints BuildGridPaints()
        {
            var gridPaint = new SKPaint();

            gridPaint.Color        = SKColors.White;
            gridPaint.IsAntialias  = false;
            gridPaint.FakeBoldText = false;
            gridPaint.IsDither     = false;
            gridPaint.StrokeWidth  = 0;
            gridPaint.Style        = SKPaintStyle.Stroke;
            var underline = gridPaint.Clone();

            underline.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(gridRect.Left - namesToFirstBeatMargin, 0),
                                                             new[] { gridPaint.Color.WithAlpha(0), gridPaint.Color.WithAlpha(125) }, null, SKShaderTileMode.Clamp);
            var horiz = gridPaint.Clone();

            horiz.Shader = SKShader.CreateLinearGradient(new SKPoint(gridRect.Left, 0), new SKPoint(gridRect.Right, 0),
                                                         new[] { gridPaint.Color.WithAlpha(125), gridPaint.Color.WithAlpha(125), gridPaint.Color.WithAlpha(0) },
                                                         new[] { 0f, 1f - timeUnitWidth / (float)gridRect.Width, 1f }, SKShaderTileMode.Clamp);
            var offBeat = gridPaint.Clone();

            offBeat.PathEffect = SKPathEffect.CreateDash(new[] { 1f, settings.LineHeight - 1 }, 1f);
            var onBeat = gridPaint.Clone();

            onBeat.Color  = gridPaint.Color.WithAlpha(125);
            onBeat.Shader = SKShader.CreateLinearGradient(new SKPoint(0, gridRect.Top + 1), new SKPoint(0, gridRect.Bottom + 20),
                                                          new[] { gridPaint.Color.WithAlpha(0), gridPaint.Color.WithAlpha(125), gridPaint.Color.WithAlpha(125), gridPaint.Color.WithAlpha(0) },
                                                          new[] { 0f, 10f / (gridRect.Height + 20), 1f - 10f / (gridRect.Height + 20), 1f }, SKShaderTileMode.Clamp);
            var timeMark = gridPaint.Clone();

            timeMark.Shader = SKShader.CreateLinearGradient(new SKPoint(0, gridRect.Top + 1), new SKPoint(0, gridRect.Bottom + 20),
                                                            new[] { gridPaint.Color.WithAlpha(0), gridPaint.Color, gridPaint.Color, gridPaint.Color.WithAlpha(0) },
                                                            new[] { 0f, 10f / (gridRect.Height + 20), 1f - 10f / (gridRect.Height + 20), 1f }, SKShaderTileMode.Clamp);
            timeMark.StrokeWidth = 3;
            return(new GridPaints
            {
                horizontalHeaderUnderline = underline,
                horizontal = horiz,
                verticalOnBeat = onBeat,
                verticalOffBeat = offBeat,
                timeMark = timeMark
            });
        }
예제 #8
0
        private void ReadTextSpans(XElement e, SKCanvas canvas, SKPoint location, SKPaint stroke, SKPaint fill)
        {
            var nodes = e.Nodes().ToArray();

            for (int i = 0; i < nodes.Length; i++)
            {
                var  c       = nodes[i];
                bool isFirst = i == 0;
                bool isLast  = i == nodes.Length - 1;

                if (c.NodeType == XmlNodeType.Text)
                {
                    // TODO: check for preserve whitespace

                    var textSegments = ((XText)c).Value.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
                    var count        = textSegments.Length;
                    if (count > 0)
                    {
                        if (isFirst)
                        {
                            textSegments[0] = textSegments[0].TrimStart();
                        }
                        if (isLast)
                        {
                            textSegments[count - 1] = textSegments[count - 1].TrimEnd();
                        }
                        var text = WSRe.Replace(string.Concat(textSegments), " ");

                        canvas.DrawText(text, location.X, location.Y, fill);

                        location.X += fill.MeasureText(text);
                    }
                }
                else if (c.NodeType == XmlNodeType.Element)
                {
                    var ce = (XElement)c;
                    if (ce.Name.LocalName == "tspan")
                    {
                        var spanFill = fill.Clone();

                        // the current span may want to change the cursor position
                        location.X = ReadOptionalNumber(ce.Attribute("x")) ?? location.X;
                        location.Y = ReadOptionalNumber(ce.Attribute("y")) ?? location.Y;

                        ReadFontAttributes(ce, spanFill);

                        var text = ce.Value.Trim();

                        canvas.DrawText(text, location.X, location.Y, spanFill);

                        location.X += spanFill.MeasureText(text);
                    }
                }
            }
        }
예제 #9
0
        public Box2 GetBounds(Node node)
        {
            var x = node.X;
            var y = node.Y;

            using var headerTextPaint = _paint.Clone().WithColor(0xFF_FFFFFF).WithTypeface(_headerTypeface);
            using var textPaint       = _paint.Clone().WithColor(0xFF_FFFFFF).WithTypeface(_nodeTypeface);

            var headerLineHeight = (int)(headerTextPaint.FontMetrics.Descent - headerTextPaint.FontMetrics.Ascent + headerTextPaint.FontMetrics.Leading);

            var lineHeight = (int)(textPaint.FontMetrics.Descent - textPaint.FontMetrics.Ascent + textPaint.FontMetrics.Leading);

            var width   = GetNodeWidth(node, headerTextPaint, textPaint);
            var numPins = Math.Max(node.InputPins.Count, node.OutputPins.Count);
            var height  = lineHeight * (numPins - 1) - textPaint.FontMetrics.Ascent + textPaint.FontMetrics.Descent + 6;

            var boundsExpansion = NodeBorderSize;

            // Selection bounds is slightly larger than render bounds to make connection hit testing more ergonomic
            return(new Box2(x - NodeBorderSize - boundsExpansion, y - headerLineHeight - boundsExpansion, x + width + NodeBorderSize + 2 * boundsExpansion,
                            y + height + NodeBorderSize + 2 * boundsExpansion));
        }
예제 #10
0
        public static void DrawText(this SKCanvas canvas, IEnumerable <SKTextRun> runs, float x, float y, SKPaint paint)
        {
            if (canvas == null)
            {
                throw new ArgumentNullException(nameof(canvas));
            }
            if (runs == null)
            {
                throw new ArgumentNullException(nameof(runs));
            }
            if (paint == null)
            {
                throw new ArgumentNullException(nameof(paint));
            }

            foreach (var run in runs)
            {
                using (var newPaint = paint.Clone())
                {
                    if (run.Typeface != null)
                    {
                        newPaint.Typeface = run.Typeface;
                    }
                    if (run.TextSize != null)
                    {
                        newPaint.TextSize = run.TextSize.Value;
                    }
                    if (run.Color != null)
                    {
                        newPaint.Color = run.Color.Value;
                    }
                    if (run.TextEncoding != null)
                    {
                        newPaint.TextEncoding = run.TextEncoding.Value;
                    }

                    if (run.Text?.Length > 0)
                    {
                        canvas.DrawText(run.Text, x + run.Offset.X, y + run.Offset.Y, newPaint);
                        x += newPaint.MeasureText(run.Text);
                    }
                }
            }
        }
예제 #11
0
        void OnTouchEffectAction(object sender, TouchActionEventArgs args)
        {
            switch (args.Type)
            {
            case TouchActionType.Pressed:
                if (!inProgressPaths.ContainsKey(args.Id))
                {
                    SKPath path = new SKPath();
                    path.MoveTo(ConvertToPixel(args.Location));
                    inProgressPaths.Add(args.Id, new Draw {
                        SKPath = path, Paint = paint.Clone()
                    });
                    canvasView.InvalidateSurface();
                }
                break;

            case TouchActionType.Moved:
                if (inProgressPaths.ContainsKey(args.Id))
                {
                    SKPath path = inProgressPaths[args.Id].SKPath;
                    path.LineTo(ConvertToPixel(args.Location));
                    canvasView.InvalidateSurface();
                }
                break;

            case TouchActionType.Released:
                if (inProgressPaths.ContainsKey(args.Id))
                {
                    completedPaths.Add(inProgressPaths[args.Id]);
                    inProgressPaths.Remove(args.Id);
                    canvasView.InvalidateSurface();
                }
                break;

            case TouchActionType.Cancelled:
                if (inProgressPaths.ContainsKey(args.Id))
                {
                    inProgressPaths.Remove(args.Id);
                    canvasView.InvalidateSurface();
                }
                break;
            }
        }
예제 #12
0
        private void Write(SKCanvas canvas, Write text)
        {
            var paint = _paintDevice.Clone();

            paint.TextAlign     = (SKTextAlign)text.Align;
            _writeTextPosition += (int)paint.TextSize;

            var x = (float)text.Offset;

            if (text.Align == Aligmnent.Right)
            {
                x = canvas.LocalClipBounds.Width;
            }
            else if (text.Align == Aligmnent.Center)
            {
                x = canvas.LocalClipBounds.Width / 2;
            }
            canvas.DrawText(text.Text, x, _writeTextPosition, paint);
        }
예제 #13
0
 public object Clone()
 {
     return(nativeFont.Clone());
 }
예제 #14
0
        internal static SKBitmap FromText(string text, SKColor color, bool isDrawRect = false)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(text))
                {
                    using (SKPaint paint = new SKPaint())
                    {
                        paint.Color                = color;
                        paint.SubpixelText         = true;
                        paint.IsEmbeddedBitmapText = true;
                        paint.IsAntialias          = true;
                        paint.TextEncoding         = SKTextEncoding.Utf32;
                        paint.TextSize             = 255;

                        float          height;
                        string[]       lines         = text.Split(splitters, StringSplitOptions.RemoveEmptyEntries);
                        string[][]     chars         = new string[lines.Length][];
                        float[][]      charsWidth    = new float[chars.Length][];
                        SKTypeface[][] charsTypeface = new SKTypeface[chars.Length][];
                        float[]        linesWidth    = new float[chars.Length];
                        float          maxLineHeight = 0;
                        float          maxLineWidth  = 0;


                        List <string> currentLineChars = new List <string>();
                        for (int i = 0; i < chars.Length; i++)
                        {
                            TextElementEnumerator strEnumerator = StringInfo.GetTextElementEnumerator(lines[i]);
                            while (strEnumerator.MoveNext())
                            {
                                currentLineChars.Add(strEnumerator.GetTextElement());
                            }

                            chars[i] = currentLineChars.ToArray();
                            currentLineChars.Clear();

                            charsTypeface[i] = new SKTypeface[chars[i].Length];
                            charsWidth[i]    = new float[chars[i].Length];

                            linesWidth[i] = 0;
                            for (int j = 0; j < chars[i].Length; j++)
                            {
                                using (SKPaint charPaint = paint.Clone())
                                {
                                    int    numberChar  = 120;
                                    char[] currentChar = chars[i][j].ToCharArray();

                                    if (currentChar?.Length > 1 && !(currentChar[1] >= 55296 && currentChar[1] <= 57000)) //checking highSurrogate
                                    {
                                        currentChar = new char[] { currentChar[0] }
                                    }
                                    ;

                                    switch (currentChar?.Length)
                                    {
                                    case 1:
                                        numberChar = Char.ConvertToUtf32(chars[i][j], 0);
                                        break;

                                    case 2:
                                        numberChar = Char.ConvertToUtf32(currentChar[0], currentChar[1]);
                                        break;

                                    case 0:
                                        chars[i][j] = $"";
                                        break;

                                    default:
                                        numberChar  = Char.ConvertToUtf32(currentChar[0], currentChar[1]);
                                        chars[i][j] = $"{currentChar[0]}{currentChar[1]}";
                                        break;
                                    }

                                    charPaint.Typeface = charsTypeface[i][j] = SKFontManager.Default.MatchCharacter(numberChar);
                                    SKRect currenttextBounds = new SKRect();
                                    charsWidth[i][j] = charPaint.MeasureText(chars[i][j], ref currenttextBounds);
                                    linesWidth[i]   += charsWidth[i][j];

                                    if (maxLineHeight < currenttextBounds.Height)
                                    {
                                        maxLineHeight = currenttextBounds.Height;
                                    }
                                }

                                if (maxLineWidth < linesWidth[i])
                                {
                                    maxLineWidth = linesWidth[i];
                                }
                            }
                        }

                        currentLineChars = null;
                        maxLineHeight    = (float)Math.Ceiling(maxLineHeight * 1.15);
                        maxLineWidth     = (float)Math.Ceiling(maxLineWidth * 1.05);
                        height           = (float)Math.Ceiling((chars.Length + 0.32f) * maxLineHeight);

                        SKBitmap textBitmap = new SKBitmap((int)maxLineWidth, (int)height);
                        SKRect   textDest   = new SKRect(0, 0, maxLineWidth, height);
                        using (SKCanvas canvasText = new SKCanvas(textBitmap))
                        {
                            canvasText.DrawBitmap(textBitmap, textDest);

                            float yText = maxLineHeight;


                            for (int i = 0; i < chars.Length; i++)
                            {
                                float xText = maxLineWidth / 2 - (linesWidth[i] / 2);

                                for (int j = 0; j < chars[i].Length; j++)
                                {
                                    using (SKPaint charPaint = paint.Clone())
                                    {
                                        charPaint.Typeface = charsTypeface[i][j];
                                        canvasText.DrawText(chars[i][j], xText, yText, charPaint);
                                        xText += charsWidth[i][j];
                                    }
                                }

                                yText += maxLineHeight;
                            }

                            if (isDrawRect)
                            {
                                using (var paintRect = paint.Clone())
                                {
                                    paintRect.Style       = SKPaintStyle.Stroke;
                                    paintRect.Color       = SKColors.White;
                                    paintRect.StrokeWidth = 3;
                                    canvasText.DrawRect(new SKRect(0, 0, maxLineWidth, height), paintRect);
                                }
                            }
                        }

                        foreach (var a in charsTypeface)
                        {
                            foreach (var b in a)
                            {
                                b.Dispose();
                            }
                        }

                        GC.Collect(0);

                        return(textBitmap);
                    }
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception)
            {
                return(null);
            }
        }
예제 #15
0
        private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill)
        {
            if (e.Attribute("display")?.Value == "none")
            {
                return;
            }

            // transform matrix
            var transform = ReadTransform(e.Attribute("transform")?.Value ?? string.Empty);

            canvas.Save();
            canvas.Concat(ref transform);

            // clip-path
            var clipPath = ReadClipPath(e.Attribute("clip-path")?.Value ?? string.Empty);

            if (clipPath != null)
            {
                canvas.ClipPath(clipPath);
            }

            // 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 "image":
            {
                var image = ReadImage(e);
                if (image.Bytes != null)
                {
                    using (var bitmap = SKBitmap.Decode(image.Bytes))
                    {
                        if (bitmap != null)
                        {
                            canvas.DrawBitmap(bitmap, image.Rect);
                        }
                    }
                }
                break;
            }

            case "text":
                if (stroke != null || fill != null)
                {
                    var spans = ReadText(e, stroke?.Clone(), fill?.Clone());
                    if (spans.Any())
                    {
                        canvas.DrawText(spans);
                    }
                }
                break;

            case "rect":
            case "ellipse":
            case "circle":
            case "path":
            case "polygon":
            case "polyline":
            case "line":
                if (stroke != null || fill != null)
                {
                    var elementPath = ReadElement(e);
                    if (elementPath != null)
                    {
                        if (fill != null)
                        {
                            canvas.DrawPath(elementPath, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawPath(elementPath, 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 "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();
        }
예제 #16
0
        private SKText ReadTextSpans(XElement e, SKPoint xy, SKTextAlign textAlign, float baselineShift, SKPaint stroke, SKPaint fill)
        {
            var spans = new SKText(xy, textAlign);

            // textAlign is used for all spans within the <text> element. If different textAligns would be needed, it is necessary to use
            // several <text> elements instead of <tspan> elements
            var currentBaselineShift = baselineShift;

            fill.TextAlign = SKTextAlign.Left;              // fixed alignment for all spans

            var nodes = e.Nodes().ToArray();

            for (int i = 0; i < nodes.Length; i++)
            {
                var  c       = nodes[i];
                bool isFirst = i == 0;
                bool isLast  = i == nodes.Length - 1;

                if (c.NodeType == XmlNodeType.Text)
                {
                    // TODO: check for preserve whitespace

                    var textSegments = ((XText)c).Value.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
                    var count        = textSegments.Length;
                    if (count > 0)
                    {
                        if (isFirst)
                        {
                            textSegments[0] = textSegments[0].TrimStart();
                        }
                        if (isLast)
                        {
                            textSegments[count - 1] = textSegments[count - 1].TrimEnd();
                        }
                        var text = WSRe.Replace(string.Concat(textSegments), " ");

                        spans.Append(new SKTextSpan(text, fill.Clone(), baselineShift: currentBaselineShift));
                    }
                }
                else if (c.NodeType == XmlNodeType.Element)
                {
                    var ce = (XElement)c;
                    if (ce.Name.LocalName == "tspan")
                    {
                        // the current span may want to change the cursor position
                        var x    = ReadOptionalNumber(ce.Attribute("x"));
                        var y    = ReadOptionalNumber(ce.Attribute("y"));
                        var text = ce.Value;                         //.Trim();

                        var spanFill = fill.Clone();
                        ReadFontAttributes(ce, spanFill);

                        // Don't read text-anchor from tspans!, Only use enclosing text-anchor from text element!
                        currentBaselineShift = ReadBaselineShift(ce);

                        spans.Append(new SKTextSpan(text, spanFill, x, y, currentBaselineShift));
                    }
                }
            }

            return(spans);
        }
예제 #17
0
        private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill)
        {
            ReadPaints(e, ref stroke, ref fill);

            // transform matrix
            var transform = ReadTransform(e.Attribute("transform")?.Value ?? string.Empty);

            canvas.Save();
            canvas.Concat(ref transform);

            // SVG elements
            var elementName = e.Name.LocalName;

            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)
                {
                    foreach (var gElement in e.Elements())
                    {
                        ReadElement(gElement, canvas, stroke?.Clone(), fill?.Clone());
                    }
                }
                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();
        }
예제 #18
0
        public override void Draw(Diagram diagram)
        {
            SKPaint paint = new SKPaint
            {
                Color       = Colour,
                IsAntialias = true,
                Typeface    = SKTypeface.FromFamilyName(FontFamily),
                TextAlign   = SKTextAlign.Center,
                TextSize    = FontSize
            };

            if (Charge != 0)
            {
                string chargeText = $"{(Math.Abs(Charge) > 1 ? (Math.Sign(Charge) * Charge).ToString() : string.Empty)}";
                if (Charge < 0)
                {
                    chargeText += '-';
                }
                else if (Charge > 0)
                {
                    chargeText += '+';
                }
                float chargeFontSize = FontSize / 2f;

                SKPaint secondPaint = paint.Clone();
                secondPaint.TextSize  = chargeFontSize;
                secondPaint.TextAlign = SKTextAlign.Left;

                diagram.DiagramSurface.Canvas.DrawText(chargeText, X + FontSize / 2.25f, Y, secondPaint);
            }

            diagram.DiagramSurface.Canvas.DrawText(Symbol, X, Y + FontSize / 2.25f, paint);

            if (LoneElectronCount > 0)
            {
                SKPaint p = new SKPaint
                {
                    Color       = Colour,
                    Style       = SKPaintStyle.Fill,
                    IsAntialias = true
                };

                double angle = (ElectronAngle / 180d) * Math.PI;
                double a1    = angle + (Math.PI / 8);
                double a2    = angle - (Math.PI / 8);

                if (LoneElectronCount >= 2)
                {
                    float dPointX1 = X + (float)((FontSize * 0.9) * Math.Cos(a1));
                    float dPointY1 = Y + (float)((FontSize * 0.9) * Math.Sin(a1));

                    float dPointX2 = X + (float)((FontSize * 0.9) * Math.Cos(a2));
                    float dPointY2 = Y + (float)((FontSize * 0.9) * Math.Sin(a2));

                    diagram.DiagramSurface.Canvas.DrawCircle(dPointX1, dPointY1, FontSize / 10.5f, p);
                    diagram.DiagramSurface.Canvas.DrawCircle(dPointX2, dPointY2, FontSize / 10.5f, p);
                }
                else
                {
                    float dPointX = X + (float)((FontSize * 0.9) * Math.Cos(angle));
                    float dPointY = Y + (float)((FontSize * 0.9) * Math.Sin(angle));

                    diagram.DiagramSurface.Canvas.DrawCircle(dPointX, dPointY, FontSize / 10.5f, p);
                }
            }

            paint.Dispose();
        }
        protected override void OnDrawSample(SKCanvas canvas, int width, int height)
        {
            canvas.DrawColor(SKColors.White);

            var basePaint = new SKPaint();

            basePaint.IsAntialias = true;
            basePaint.TextSize    = 60;

            // first, we can just use a font (system default if not exists)
            using (var paint = basePaint.Clone())
                using (var courier = SKTypeface.FromFamilyName("Courier New"))
                {
                    paint.Typeface = courier;
                    canvas.DrawText("'A', 'ݐ', '年'", 40, 100, paint);
                }

            // the font manager finds fonts
            var fontManager = SKFontManager.Default;

            // or, we can try and make sure that we have the character, and hope it has the others
            using (var paint = basePaint.Clone())
                using (var courier = fontManager.MatchCharacter("Courier New", 'ݐ'))
                {
                    paint.Typeface = courier;
                    canvas.DrawText("'A', 'ݐ', '年'", 40, 200, paint);
                }

            // if we know the font doesn't have the character, or don't want to fall back
            using (var paint = basePaint.Clone())
                using (var courier = SKTypeface.FromFamilyName("Courier New"))
                    using (var arabic = fontManager.MatchCharacter("Courier New", 'ݐ'))
                        using (var japanese = fontManager.MatchCharacter("Courier New", '年'))
                        {
                            var first    = "'A', '";
                            var arabChar = "ݐ";
                            var mid      = "', '";
                            var japChar  = "年";
                            var last     = "'";

                            float x = 40;

                            // draw the first bit
                            paint.Typeface = courier;
                            canvas.DrawText(first, x, 300, paint);
                            x += paint.MeasureText(first);

                            // the arab character
                            paint.Typeface = arabic;
                            canvas.DrawText(arabChar, x, 300, paint);
                            x += paint.MeasureText(arabChar);

                            // draw the next bit
                            paint.Typeface = courier;
                            canvas.DrawText(mid, x, 300, paint);
                            x += paint.MeasureText(mid);

                            // the japanese character
                            paint.Typeface = japanese;
                            canvas.DrawText(japChar, x, 300, paint);
                            x += paint.MeasureText(japChar);

                            // the end
                            paint.Typeface = courier;
                            canvas.DrawText(last, x, 300, paint);
                        }

            // let's draw some emojis (UTF-32 characters)
            var emojiChar = StringUtilities.GetUnicodeCharacterCode("🚀", SKTextEncoding.Utf32);

            using (var paint = basePaint.Clone())
                using (var emoji = fontManager.MatchCharacter(emojiChar))
                {
                    paint.Typeface = emoji;
                    canvas.DrawText("🌐 🍪 🍕 🚀", 40, 400, paint);
                }
        }
예제 #20
0
 public SKSvgMask(SKPaint fill, XElement element)
 {
     Fill    = fill.Clone();
     Element = element;
 }
예제 #21
0
 public SKSvgMask(SKPaint stroke, SKPaint fill, XElement element)
 {
     Stroke  = stroke?.Clone();
     Fill    = fill?.Clone();
     Element = element;
 }