public static SKPaint ScaledPaint(float scale, SKPaint paint) { var cpy = paint.Clone(); cpy.TextSize *= scale; return(cpy); }
SKPaint ScalePaint(SKPaint paint) { paint = paint.Clone(); paint.TextSize *= Scale; paint.StrokeWidth *= Scale; return(paint); }
private void LoadElements(IEnumerable <XElement> elements, SKCanvas canvas, SKPaint stroke, SKPaint fill) { foreach (var e in elements) { ReadElement(e, canvas, stroke?.Clone(), fill?.Clone()); } }
public Brush Clone() { return(new SolidBrush() { nativeBrush = nativeBrush?.Clone() }); }
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); } }
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); } }
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 }); }
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); } } } }
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)); }
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); } } } }
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; } }
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); }
public object Clone() { return(nativeFont.Clone()); }
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); } }
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(); }
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); }
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(); }
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); } }
public SKSvgMask(SKPaint fill, XElement element) { Fill = fill.Clone(); Element = element; }
public SKSvgMask(SKPaint stroke, SKPaint fill, XElement element) { Stroke = stroke?.Clone(); Fill = fill?.Clone(); Element = element; }