public /*interface ChartPainter*/ void DrawCourseRange(List <KChartEntry> list, int seriesIndex, SKColor color, Swipe pinchPan) { if (list.Count == 1) { DrawCircle(list[0].Ypoint[seriesIndex], pinchPan % 8, FillPaint(color)); } if (list.Count > 1) { canvas.SetFillColor(CG.Color(color)); var path = new CGPath(); KChartEntry entry0 = list[0]; SKPoint meanPoint0 = entry0.Ypoint[seriesIndex]; float range0 = entry0.YpointRange[seriesIndex]; path.MoveToPoint(CG.Point(pinchPan % new SKPoint(meanPoint0.X, meanPoint0.Y + range0))); path.AddLineToPoint(CG.Point(pinchPan % new SKPoint(meanPoint0.X, meanPoint0.Y - range0))); for (int i = 0; i < list.Count; i++) { KChartEntry entry = list[i]; SKPoint meanPoint = entry.Ypoint[seriesIndex]; float range = entry.YpointRange[seriesIndex]; path.AddLineToPoint(CG.Point(pinchPan % new SKPoint(meanPoint.X, meanPoint.Y - range))); } for (int i = list.Count - 1; i >= 0; i--) { KChartEntry entry = list[i]; SKPoint meanPoint = entry.Ypoint[seriesIndex]; float range = entry.YpointRange[seriesIndex]; path.AddLineToPoint(CG.Point(pinchPan % new SKPoint(meanPoint.X, meanPoint.Y + range))); } path.CloseSubpath(); canvas.AddPath(path); canvas.FillPath(); } }
public /* Interface KGuiControl */ void GuiChartSnap() { if (NSThread.IsMain) { CGBitmapContext theCanvas = null; // store the canvas internally generated by GenPainter for use by DoPaste Func <Colorer> GenColorer = () => { return(new CGColorer()); }; Func <SKSize, ChartPainter> GenPainter = (SKSize canvasSize) => { CGBitmapContext canvas = CG.Bitmap((int)canvasSize.Width, (int)canvasSize.Height); CG.FlipCoordinateSystem(canvas); theCanvas = canvas; return(new CGChartPainter(canvas)); }; Action <CGBitmapContext> DoPaste = (CGBitmapContext canvas) => { var pasteboard = NSPasteboard.GeneralPasteboard; pasteboard.ClearContents(); pasteboard.WriteObjects(new NSImage[] { new NSImage(canvas.ToImage(), new CGSize(canvas.Width, canvas.Height)) }); }; CGSize cgChartSize = this.kaemikaChart.Frame.Size; Export.Snap(GenColorer, GenPainter, new SKSize((float)cgChartSize.Width, (float)cgChartSize.Height)); try { DoPaste(theCanvas); } catch { } } else { _ = BeginInvokeOnMainThreadAsync(() => { GuiChartSnap(); return(ack); }).Result; } }
// Implement this to draw on the canvas. public override void DrawRect(CGRect dirtyRect) { base.DrawRect(dirtyRect); var context = NSGraphicsContext.CurrentContext.CGContext; CG.FlipCoordinateSystem(context); KDeviceHandler.Draw(new CGDevicePainter(context), 0, 0, (int)dirtyRect.Width, (int)dirtyRect.Height); }
public override /*interface Colorer*/ SKRect MeasureText(string text, SKPaint paint) { if (string.IsNullOrEmpty(text)) { return(new SKRect(0, 0, 0, 0)); } CGRect rect = CG.MeasureText(text, paint); return(new SKRect((float)rect.Left, (float)rect.Top, (float)rect.Right, (float)rect.Bottom)); }
public void DrawBackground(CGContext canvas, float canvasX, float canvasY, float canvasWidth, float canvasHeight) { var backPaint = CG.Color(KDeviceHandler.deviceBackColor); canvas.SetFillColor(backPaint); var path = new CGPath(); path.AddRect(new CGRect(canvasX, canvasY, canvasWidth, canvasHeight)); canvas.AddPath(path); canvas.FillPath(); }
public static void DrawPolygon(CGContext canvas, List <SKPoint> points, SKPaint paint) { if (points.Count > 1) { var path = new CGPath(); path.MoveToPoint(CG.Point(points[0])); for (int i = 0; i < points.Count; i++) { path.AddLineToPoint(CG.Point(points[i])); } PaintPath(canvas, path, paint); } }
public void DrawDropletLabel(CGContext canvas, string label, SKPoint center, float radius, float strokeWidth, bool biggie, Swipe swipe) { using (var labelPaint = new SKPaint { Style = SKPaintStyle.Stroke, TextSize = swipe % (0.5f * radius), TextAlign = SKTextAlign.Center, Color = new SKColor(255, 255, 255, 191), StrokeWidth = swipe % strokeWidth, IsAntialias = true }) { CG.DrawTextS(canvas, label, swipe % new SKPoint(center.X, center.Y + 0.1f * radius), labelPaint); if (biggie) { CG.DrawTextS(canvas, ">4μL", swipe % new SKPoint(center.X, center.Y + 0.6f * radius), labelPaint); } } }
public void DrawDevice(KDeviceHandler.KDevice device, CGContext canvas, float canvasX, float canvasY, float canvasWidth, float canvasHeight, float deviceX, float deviceY, float deviceWidth, float deviceHeight, float padRadius, float margin, Swipe swipe) { DrawBackground(canvas, canvasX, canvasY, canvasWidth, canvasHeight); float padStrokeWidth = padRadius / 10.0f; float padStrokeWidthAccent = 0.75f * padStrokeWidth; SKRect coldZoneRect = new SKRect(deviceX + margin, deviceY + margin, deviceX + margin + device.coldZoneWidth * 2 * padRadius, deviceY + margin + device.rowsNo * 2 * padRadius); SKRect hotZoneRect = new SKRect(deviceX + margin + (device.coldZoneWidth + device.warmZoneWidth) * 2 * padRadius, deviceY + margin, deviceX + margin + (device.coldZoneWidth + device.warmZoneWidth + device.hotZoneWidth) * 2 * padRadius, deviceY + margin + device.rowsNo * 2 * padRadius); DrawHeatZone(canvas, coldZoneRect, padRadius, coldZoneRect.Width / (2 * device.coldZoneWidth), coldColor, swipe); DrawHeatZone(canvas, hotZoneRect, padRadius, hotZoneRect.Width / (2 * device.hotZoneWidth), hotColor, swipe); using (var zoneTextPaint = new SKPaint { Style = SKPaintStyle.Fill, TextSize = swipe % padRadius, TextAlign = SKTextAlign.Center, Color = SKColors.Blue, IsAntialias = true }) { CG.DrawTextS(canvas, "< " + KDeviceHandler.coldTemp, swipe % new SKPoint(coldZoneRect.MidX, coldZoneRect.Bottom + margin), zoneTextPaint); CG.DrawTextS(canvas, "> " + KDeviceHandler.hotTemp, swipe % new SKPoint(hotZoneRect.MidX, hotZoneRect.Bottom + margin), zoneTextPaint); } float strokePaintStrokeWidth = padStrokeWidth; float strokeAccentPaintStrokeWidth = padStrokeWidthAccent; using (var strokePaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Black, StrokeWidth = swipe % strokePaintStrokeWidth, StrokeJoin = SKStrokeJoin.Round, IsAntialias = true }) using (var strokeAccentPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.White, StrokeWidth = swipe % strokeAccentPaintStrokeWidth, StrokeJoin = SKStrokeJoin.Round, StrokeCap = SKStrokeCap.Round, IsAntialias = true }) using (var fillPaint = new SKPaint { Style = SKPaintStyle.Fill, Color = SKColors.Goldenrod, IsAntialias = true }) // SKColors.DarkGoldenrod / Goldenrod / PaleGoldenrod / LightGoldenrodYellow / Gold using (var holePaint = new SKPaint { Style = SKPaintStyle.Fill, Color = SKColors.Black, IsAntialias = true }) using (var holeAccentPaint = new SKPaint { Style = SKPaintStyle.Fill, Color = SKColors.White, IsAntialias = true }) { for (int j = 0; j < device.rowsNo; j++) { for (int i = 0; i < device.colsNo; i++) { DrawPad(canvas, new SKPoint(deviceX + margin + padRadius + i * 2 * padRadius, deviceY + margin + padRadius + j * 2 * padRadius), padRadius, strokePaint, strokePaintStrokeWidth, fillPaint, holePaint, strokeAccentPaint, strokeAccentPaintStrokeWidth, holeAccentPaint, swipe); } } } }
public void DrawHeatZone(CGContext canvas, SKRect zone, float halo, float groove, SKColor color, Swipe swipe) { var radialGradient = SKShader.CreateRadialGradient(swipe % new SKPoint(zone.MidX, zone.MidY), swipe % groove, new SKColor[2] { color, KDeviceHandler.deviceBackColor }, null, SKShaderTileMode.Mirror); //, scaleMatrix); using (var gradientPaint = new SKPaint { Style = SKPaintStyle.Fill, Shader = radialGradient }) { var path = new CGPath(); path.AddRoundedRect(CG.Rect(swipe % InflateRect(zone, halo)), swipe % halo, swipe % halo); canvas.AddPath(path); canvas.SetFillColor(CG.Color(color)); canvas.FillPath(); } }
private static CGPath AddBeziers(CGPath path, SKPoint[] controlPoints) { path.MoveToPoint(CG.Point(controlPoints[0])); for (int i = 0; i < controlPoints.Length - 2; i += 4) { if (i + 3 > controlPoints.Length - 1) { var cp = CG.Point(controlPoints[i + 1]); var p = CG.Point(controlPoints[i + 2]); path.AddQuadCurveToPoint(cp.X, cp.Y, p.X, p.Y); } else { path.AddCurveToPoint(CG.Point(controlPoints[i + 1]), CG.Point(controlPoints[i + 2]), CG.Point(controlPoints[i + 3])); } } return(path); }
// using the attributes of SKPaint paint parameter: //Typeface, //TextSize, //TextAlign(Center|Left), //Style(Fill|Stroke), //Color, //StrokeWidth(if Style=Stroke) public static CGSize DrawTextS(CGContext canvas, string text, SKPoint point, SKPaint paint) { // BASIC TEXT DRAWING IN CGContext: //canvas.SetTextDrawingMode(toCGTextDrawingMode(paint.Style)); //canvas.SetFillColor(CGUtil.toCGColor(paint.Color)); //canvas.SetStrokeColor(CGUtil.toCGColor(paint.Color)); //canvas.SetLineWidth(paint.StrokeWidth); //canvas.SelectFont("Helvetica", paint.TextSize, CGTextEncoding.MacRoman); //// upsidedown text: https://stackoverflow.com/questions/44122778/ios-swift-core-graphics-string-is-upside-down //canvas.SaveState(); //canvas.TranslateCTM(center.X, center.Y); // text should be centered, but isn't //canvas.ScaleCTM(1, -1); //canvas.ShowTextAtPoint(0, 0, text); //canvas.RestoreState(); // TEXT DRAWING IN CoreText to compute text size: // https://docs.microsoft.com/en-us/dotnet/api/foundation.nsattributedstring?view=xamarin-ios-sdk-12 var typeface = (paint.Typeface == null) ? "Helvetica" : paint.Typeface.FamilyName; var attributedString = new Foundation.NSAttributedString(text, new CoreText.CTStringAttributes() { ForegroundColor = Color(paint.Color), // ForegroundColor is used (only?) if paint.Style = Fill, and overrides paint.Color Font = new CoreText.CTFont(typeface, paint.TextSize) }); var textLine = new CoreText.CTLine(attributedString); CGSize textSize = attributedString.Size; // maybe we can extract the true baseline origin and return a Rect instead of a Size? bool centered = paint.TextAlign == SKTextAlign.Center; CGPoint textStart = (centered) ? new CGPoint(point.X - textSize.Width / 2.0f, point.Y) : Point(point); canvas.SetTextDrawingMode(CG.TextDrawingMode(paint.Style)); canvas.SetStrokeColor(CG.Color(paint.Color)); // paint.Color is used (only?) if paint.Style = Stroke canvas.SetLineWidth(paint.StrokeWidth); // upsidedown text: https://stackoverflow.com/questions/44122778/ios-swift-core-graphics-string-is-upside-down canvas.SaveState(); canvas.TranslateCTM(textStart.X, textStart.Y); canvas.ScaleCTM(1, -1); canvas.TextPosition = new CGPoint(0, 0); // because of the translation textLine.Draw(canvas); canvas.RestoreState(); return(textSize); }
public /*interface ChartPainter*/ void DrawCourseFill(List <KChartEntry> list, int seriesIndex, float bottom, SKColor color, Swipe pinchPan) { if (list.Count > 1) { canvas.SetFillColor(CG.Color(color)); var path = new CGPath(); path.MoveToPoint(CG.Point(pinchPan % new SKPoint(list[0].Ypoint[seriesIndex].X, bottom))); path.AddLineToPoint(CG.Point(pinchPan % list[0].Ypoint[seriesIndex])); for (int i = 0; i < list.Count; i++) { path.AddLineToPoint(CG.Point(pinchPan % list[i].Ypoint[seriesIndex])); } path.AddLineToPoint(CG.Point(pinchPan % new SKPoint(list[list.Count - 1].Ypoint[seriesIndex].X, bottom))); path.CloseSubpath(); canvas.AddPath(path); canvas.FillPath(); } }
private static void PaintPath(CGContext canvas, CGPath path, SKPaint paint) { if (paint.IsStroke) { canvas.SetStrokeColor(CG.Color(paint.Color)); canvas.SetLineWidth(paint.StrokeWidth); canvas.SetLineCap(LineCap(paint.StrokeCap)); canvas.SetLineJoin(LineJoin(paint.StrokeJoin)); canvas.AddPath(path); canvas.StrokePath(); } else { canvas.SetFillColor(CG.Color(paint.Color)); canvas.AddPath(path); canvas.ClosePath(); canvas.FillPath(); } }
public /*interface ChartPainter*/ void DrawCourse(List <KChartEntry> list, int seriesIndex, float pointSize, SKColor color, Swipe pinchPan) { if (list.Count == 1) { DrawCircle(list[0].Ypoint[seriesIndex], pinchPan % 8, FillPaint(color)); } if (list.Count > 1) { canvas.SetStrokeColor(CG.Color(color)); canvas.SetLineWidth(pointSize); var path = new CGPath(); path.MoveToPoint(CG.Point(pinchPan % list[0].Ypoint[seriesIndex])); for (int i = 0; i < list.Count; i++) { path.AddLineToPoint(CG.Point(pinchPan % list[i].Ypoint[seriesIndex])); } canvas.AddPath(path); canvas.StrokePath(); } }
public void SetLegendImage(KSeries series) { NSImage nsImage; int thickness = (series.lineStyle == KLineStyle.Thick) ? 3 : (series.lineMode == KLineMode.Line) ? 1 : 8; const int height = 16; const int width = 50; const int padding = 1; const int frame = 3; const int left = 0; int framedH = thickness + 2 * frame; int framedY = (height - 2 * padding - framedH) / 2; int framedW = width - 2 * padding; int framedX = left + padding; using (CGBitmapContext bitmap = CG.Bitmap(left + width, height)) { CG.DrawRect(bitmap, new CGRect(0, 0, left + width, height), CG.Color(new SKColor(0, 0, 0, 0))); // transparent if (series.visible) { CG.DrawRect(bitmap, new CGRect(framedX, framedY, framedW, framedH), CG.Color(SKColors.White)); CG.DrawRect(bitmap, new CGRect(framedX + frame, framedY + frame, framedW - 2 * frame, thickness), CG.Color(series.color)); } using (CGImage cgImage = bitmap.ToImage()) { nsImage = new NSImage(cgImage, new CGSize(cgImage.Width, cgImage.Height)); } } this.imageDM = nsImage; this.imageLM = nsImage; this.button.Image = nsImage; }
public /*interface Painter*/ void DrawRect(SKRect rect, SKPaint paint) { CG.DrawRect(canvas, CG.Rect(rect), paint); }
public /*interface Painter*/ void DrawSpline(List <SKPoint> points, SKPaint paint) { CG.DrawSpline(canvas, points, paint); }
public /*interface Painter*/ void DrawPolygon(List <SKPoint> points, SKPaint paint) { CG.DrawPolygon(canvas, points, paint); }
public /*interface Painter*/ void Clear(SKColor background) { canvas.SetFillColor(CG.Color(background)); canvas.FillRect(canvas.GetClipBoundingBox()); }
public /*interface Painter*/ void DrawText(string text, SKPoint point, SKPaint paint) { CG.DrawTextS(canvas, text, point, paint); }
public void DrawDropletPulledVer(CGContext canvas, string label, bool biggie, SKPoint c1, SKPoint c2, KDeviceHandler.Direction dir, float r, float r1, float neckX, float r2, float textStrokeWidth, SKPaint fillPaint, float strokeWidth, float accentStrokeWidth, Swipe swipe) { float ratio = ((r1 + r2) / 2) / r; //strokeWidth = strokeWidth * ratio; textStrokeWidth = textStrokeWidth * ratio; accentStrokeWidth = accentStrokeWidth * ratio; float lr = r1 - (strokeWidth + accentStrokeWidth) / 2.0f; float dr = r2 - (strokeWidth + accentStrokeWidth) / 2.0f; // place the neck in an Y-position proportional to the rate between r1 and r2, with m1+r1Y to the top leading to c1.Y, and m2+r2Y to the bot leading to c2.Y float m1 = (2 * r - (r1 + r2)) / (1 + r2 / r1); float m2 = m1 * r2 / r1; // position of the neck float nY = c1.Y + r1 + m1; float nX = c1.X; // Control points: a1*2 is on a line from nY,nX-neckX to c1.Y,c.X-r1 where it intersects c1.Y+r1; we divide it by 2 to make the curve smoother float a1 = (m1 * (r1 - neckX) / (r1 + m1)) / 2; float a2 = (m2 * (r2 - neckX) / (r2 + m2)) / 2; var path = new CGPath(); path.MoveToPoint(CG.Point(swipe % new SKPoint(c1.X - r1, c1.Y))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c1.X - r1, c1.Y + 0.5f * r1)), CG.Point(swipe % new SKPoint(nX - (neckX + a1), c1.Y + r1)), CG.Point(swipe % new SKPoint(nX - neckX, nY))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(nX - (neckX + a2), c2.Y - r2)), CG.Point(swipe % new SKPoint(c2.X - r2, c2.Y - 0.5f * r2)), CG.Point(swipe % new SKPoint(c2.X - r2, c2.Y))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c2.X - r2, c2.Y + 0.75f * r2)), CG.Point(swipe % new SKPoint(c2.X - 0.75f * r2, c2.Y + r2)), CG.Point(swipe % new SKPoint(c2.X, c2.Y + r2))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c2.X + 0.75f * r2, c2.Y + r2)), CG.Point(swipe % new SKPoint(c2.X + r2, c2.Y + 0.75f * r2)), CG.Point(swipe % new SKPoint(c2.X + r2, c2.Y))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c2.X + r2, c2.Y - 0.5f * r2)), CG.Point(swipe % new SKPoint(nX + (neckX + a2), c2.Y - r2)), CG.Point(swipe % new SKPoint(nX + neckX, nY))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(nX + (neckX + a1), c1.Y + r1)), CG.Point(swipe % new SKPoint(c1.X + r1, c1.Y + 0.5f * r1)), CG.Point(swipe % new SKPoint(c1.X + r1, c1.Y))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c1.X + r1, c1.Y - 0.75f * r1)), CG.Point(swipe % new SKPoint(c1.X + 0.75f * r1, c1.Y - r1)), CG.Point(swipe % new SKPoint(c1.X, c1.Y - r1))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c1.X - 0.75f * r1, c1.Y - r1)), CG.Point(swipe % new SKPoint(c1.X - r1, c1.Y - 0.75f * r1)), CG.Point(swipe % new SKPoint(c1.X - r1, c1.Y))); path.CloseSubpath(); var darkPath = new CGPath(); darkPath.MoveToPoint(CG.Point(swipe % new SKPoint(c2.X, c2.Y + dr))); darkPath.AddCurveToPoint(CG.Point(swipe % new SKPoint(c2.X + 0.75f * dr, c2.Y + dr)), CG.Point(swipe % new SKPoint(c2.X + dr, c2.Y + 0.75f * dr)), CG.Point(swipe % new SKPoint(c2.X + dr, c2.Y))); var lightPath = new CGPath(); lightPath.MoveToPoint(CG.Point(swipe % new SKPoint(c1.X, c1.Y - lr))); lightPath.AddCurveToPoint(CG.Point(swipe % new SKPoint(c1.X - 0.75f * lr, c1.Y - lr)), CG.Point(swipe % new SKPoint(c1.X - lr, c1.Y - 0.75f * lr)), CG.Point(swipe % new SKPoint(c1.X - lr, c1.Y))); using (var strokePaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = new SKColor(0, 0, 0, 191), StrokeWidth = swipe % strokeWidth, IsAntialias = true }) using (var accentLightPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = new SKColor(255, 255, 255, 191), StrokeWidth = swipe % accentStrokeWidth, StrokeCap = SKStrokeCap.Round, IsAntialias = true }) using (var accentDarkPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = new SKColor(0, 0, 0, 95), StrokeWidth = swipe % accentStrokeWidth, StrokeCap = SKStrokeCap.Round, IsAntialias = true }) { canvas.AddPath(path); canvas.SetFillColor(CG.Color(fillPaint.Color)); canvas.FillPath(); canvas.AddPath(darkPath); canvas.SetStrokeColor(CG.Color(accentDarkPaint.Color)); canvas.SetLineWidth(accentDarkPaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(accentDarkPaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(accentDarkPaint.StrokeCap)); canvas.StrokePath(); canvas.AddPath(lightPath); canvas.SetStrokeColor(CG.Color(accentLightPaint.Color)); canvas.SetLineWidth(accentLightPaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(accentLightPaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(accentLightPaint.StrokeCap)); canvas.StrokePath(); canvas.AddPath(path); canvas.SetStrokeColor(CG.Color(strokePaint.Color)); canvas.SetLineWidth(strokePaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(strokePaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(strokePaint.StrokeCap)); canvas.StrokePath(); } float rYtext = (r1 == r2) ? ((dir == KDeviceHandler.Direction.Top) ? r1 : r2) : (r1 > r2) ? r1 : r2; SKPoint cText = (r1 == r2) ? ((dir == KDeviceHandler.Direction.Top) ? c1 : c2) : (r1 > r2) ? c1 : c2; DrawDropletLabel(canvas, label, cText, rYtext, textStrokeWidth, biggie, swipe); }
public /*interface Painter*/ void DrawRoundRect(SKRect rect, float padding, SKPaint paint) { CG.DrawRoundRect(canvas, rect, padding, paint); }
public /*interface Painter*/ void DrawCircle(SKPoint p, float radius, SKPaint paint) { CG.DrawCircle(canvas, p, radius, paint); }
public void DrawDroplet(CGContext canvas, string label, bool biggie, SKPoint center, float padRadius, float radius, float textStrokeWidth, SKPaint fillPaint, float strokeWidth, float accentStrokeWidth, Swipe swipe) { float ratio = radius / padRadius; //strokeWidth = strokeWidth * ratio; textStrokeWidth = textStrokeWidth * ratio; accentStrokeWidth = accentStrokeWidth * ratio; float pull = 0.75f; float accentRadius = radius - (strokeWidth + accentStrokeWidth) / 2.0f; var path = new CGPath(); path.MoveToPoint(CG.Point(swipe % new SKPoint(center.X, center.Y - radius))); // The parameters to CGPath.AddCurveToPoint are in the same order as in SKPath.CubicTo (despite what the Apple docs seem to say). path.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X + pull * radius, center.Y - radius)), CG.Point(swipe % new SKPoint(center.X + radius, center.Y - pull * radius)), CG.Point(swipe % new SKPoint(center.X + radius, center.Y))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X + radius, center.Y + pull * radius)), CG.Point(swipe % new SKPoint(center.X + pull * radius, center.Y + radius)), CG.Point(swipe % new SKPoint(center.X, center.Y + radius))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X - pull * radius, center.Y + radius)), CG.Point(swipe % new SKPoint(center.X - radius, center.Y + pull * radius)), CG.Point(swipe % new SKPoint(center.X - radius, center.Y))); path.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X - radius, center.Y - pull * radius)), CG.Point(swipe % new SKPoint(center.X - pull * radius, center.Y - radius)), CG.Point(swipe % new SKPoint(center.X, center.Y - radius))); path.CloseSubpath(); var darkPath = new CGPath(); darkPath.MoveToPoint(CG.Point(swipe % new SKPoint(center.X + accentRadius, center.Y))); darkPath.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X + accentRadius, center.Y + pull * accentRadius)), CG.Point(swipe % new SKPoint(center.X + pull * accentRadius, center.Y + accentRadius)), CG.Point(swipe % new SKPoint(center.X, center.Y + accentRadius))); var lightPath = new CGPath(); lightPath.MoveToPoint(CG.Point(swipe % new SKPoint(center.X - accentRadius, center.Y))); lightPath.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X - accentRadius, center.Y - pull * accentRadius)), CG.Point(swipe % new SKPoint(center.X - pull * accentRadius, center.Y - accentRadius)), CG.Point(swipe % new SKPoint(center.X, center.Y - accentRadius))); using (var strokePaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = new SKColor(0, 0, 0, 191), StrokeWidth = swipe % strokeWidth, IsAntialias = true }) using (var accentLightPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = new SKColor(255, 255, 255, 191), StrokeWidth = swipe % accentStrokeWidth, StrokeCap = SKStrokeCap.Round, IsAntialias = true }) using (var accentDarkPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = new SKColor(0, 0, 0, 95), StrokeWidth = swipe % accentStrokeWidth, StrokeCap = SKStrokeCap.Round, IsAntialias = true }) { canvas.AddPath(path); canvas.SetFillColor(CG.Color(fillPaint.Color)); canvas.FillPath(); canvas.AddPath(darkPath); canvas.SetStrokeColor(CG.Color(accentDarkPaint.Color)); canvas.SetLineWidth(accentDarkPaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(accentDarkPaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(accentDarkPaint.StrokeCap)); canvas.StrokePath(); canvas.AddPath(lightPath); canvas.SetStrokeColor(CG.Color(accentLightPaint.Color)); canvas.SetLineWidth(accentLightPaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(accentLightPaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(accentLightPaint.StrokeCap)); canvas.StrokePath(); canvas.AddPath(path); canvas.SetStrokeColor(CG.Color(strokePaint.Color)); canvas.SetLineWidth(strokePaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(strokePaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(strokePaint.StrokeCap)); canvas.StrokePath(); } DrawDropletLabel(canvas, label, center, radius, textStrokeWidth, biggie, swipe); }
public /*interface DevicePainter*/ void Draw(KDeviceHandler.KDevice device, int canvasX, int canvasY, int canvasWidth, int canvasHeight) { (float margin, float padRadius, float deviceWidth, float deviceHeight) = device.FittedDimensions(canvasWidth, canvasHeight); float strokeWidth = padRadius / 10.0f; float accentStrokeWidth = 1.5f * strokeWidth; float textStrokeWidth = accentStrokeWidth / 2.0f; float deviceX = canvasX + (canvasWidth - deviceWidth) / 2.0f; float deviceY = canvasY + (canvasHeight - deviceHeight) / 2.0f; // don't lock device here, it will dedlock if (device.sizeChanged || cachedBackground == null || cachedBackground.Width != canvasWidth || cachedBackground.Height != canvasHeight) { cachedBackground = CG.Bitmap(canvasWidth, canvasHeight); DrawDevice(device, cachedBackground, canvasX, canvasY, canvasWidth, canvasHeight, deviceX, deviceY, deviceWidth, deviceHeight, padRadius, margin, device.pinchPan); device.sizeChanged = false; } if (!device.sizeChanged) { // copy cachedBackground to canvas DOH! canvas.AsBitmapContext().DrawImage(new CGRect(0, 0, cachedBackground.Width, cachedBackground.Height), cachedBackground.ToImage()); // do not apply pinchPan: background bitmap is alread scaled by it } if (device.displayPinchOrigin) { // same as: GraphSharp.GraphLayout.CanvasDrawCircle(canvas, pinchOrigin, 20, false, SKColors.LightGray); // same as: using (var paint = FillPaint(SKColors.LightGray)) { painter.DrawCircle(pinchOrigin, 20, paint); } //using (var paint = new SKPaint()) { // paint.TextSize = 10; paint.IsAntialias = true; paint.Color = SKColors.LightGray; paint.IsStroke = false; // canvas.DrawCircle(device.pinchOrigin.X, device.pinchOrigin.Y, 20, paint); //} } using (var dropletFillPaint = new SKPaint { Style = SKPaintStyle.Fill, Color = device.dropletColor, IsAntialias = true }) using (var dropletBiggieFillPaint = new SKPaint { Style = SKPaintStyle.Fill, Color = device.dropletBiggieColor, IsAntialias = true }) { KDeviceHandler.Place[,] places = device.places; KDeviceHandler.Placement placement = device.placement; for (int row = 0; row < places.GetLength(0); row++) { for (int col = 0; col < places.GetLength(1); col++) { KDeviceHandler.Place place = places[row, col]; if (place != null && placement.IsOccupied(place)) { SampleValue sample = placement.SampleOf(place); float volumeRadius = padRadius * (float)Math.Sqrt((sample.Volume()) * 1000000.0); // normal radius = 1μL float diameter = 2 * padRadius; SKPaint fillPaint = dropletFillPaint; bool biggie = false; if (volumeRadius > 2 * padRadius) { biggie = true; volumeRadius = 2 * padRadius; fillPaint = dropletBiggieFillPaint; } SKPoint here = new SKPoint(deviceX + margin + padRadius + col * diameter, deviceY + margin + padRadius + row * diameter); SKPoint rht = new SKPoint(deviceX + margin + padRadius + (col + 1) * diameter, deviceY + margin + padRadius + row * diameter); SKPoint lft = new SKPoint(deviceX + margin + padRadius + (col - 1) * diameter, deviceY + margin + padRadius + row * diameter); SKPoint bot = new SKPoint(deviceX + margin + padRadius + col * diameter, deviceY + margin + padRadius + (row + 1) * diameter); SKPoint top = new SKPoint(deviceX + margin + padRadius + col * diameter, deviceY + margin + padRadius + (row - 1) * diameter); string label = sample.symbol.Raw(); // sample.FormatSymbol(placement.StyleOf(sample, style)) if (place.IsAnimation(KDeviceHandler.Animation.None)) { DrawDroplet(canvas, label, biggie, here, padRadius, volumeRadius, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.SizeHalf)) { DrawDroplet(canvas, label, biggie, here, padRadius, volumeRadius / 2, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.SizeQuarter)) { DrawDroplet(canvas, label, biggie, here, padRadius, volumeRadius / 4, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.PullRht)) { DrawDropletPulledHor(canvas, label, biggie, here, rht, KDeviceHandler.Direction.Rht, padRadius, volumeRadius * 5 / 6, volumeRadius * 5 / 12, volumeRadius * 1 / 3, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.SplitRht)) { DrawDropletPulledHor(canvas, label, biggie, here, rht, KDeviceHandler.Direction.Rht, padRadius, volumeRadius * 2 / 3, volumeRadius * 1 / 3, volumeRadius * 2 / 3, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.PullLft)) { DrawDropletPulledHor(canvas, label, biggie, lft, here, KDeviceHandler.Direction.Lft, padRadius, volumeRadius * 1 / 3, volumeRadius * 5 / 12, volumeRadius * 5 / 6, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.SplitLft)) { DrawDropletPulledHor(canvas, label, biggie, lft, here, KDeviceHandler.Direction.Lft, padRadius, volumeRadius * 2 / 3, volumeRadius * 1 / 3, volumeRadius * 2 / 3, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.PullBot)) { DrawDropletPulledVer(canvas, label, biggie, here, bot, KDeviceHandler.Direction.Bot, padRadius, volumeRadius * 5 / 6, volumeRadius * 5 / 12, volumeRadius * 1 / 3, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.SplitBot)) { DrawDropletPulledVer(canvas, label, biggie, here, bot, KDeviceHandler.Direction.Bot, padRadius, volumeRadius * 2 / 3, volumeRadius * 1 / 3, volumeRadius * 2 / 3, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.PullTop)) { DrawDropletPulledVer(canvas, label, biggie, top, here, KDeviceHandler.Direction.Top, padRadius, volumeRadius * 1 / 3, volumeRadius * 5 / 12, volumeRadius * 5 / 6, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } if (place.IsAnimation(KDeviceHandler.Animation.SplitTop)) { DrawDropletPulledVer(canvas, label, biggie, top, here, KDeviceHandler.Direction.Top, padRadius, volumeRadius * 2 / 3, volumeRadius * 1 / 3, volumeRadius * 2 / 3, textStrokeWidth, fillPaint, strokeWidth, accentStrokeWidth, device.pinchPan); } } } } } canvas.Flush(); }
public void DrawPad(CGContext canvas, SKPoint center, float radius, SKPaint strokePaint, float strokePaintStrokeWidth, SKPaint fillPaint, SKPaint holePaint, SKPaint strokeAccentPaint, float strokeAccentPaintStrokeWidth, SKPaint holeAccentPaint, Swipe swipe) { float step = radius / 7.0f; float holeRadius = radius / 7.0f; float orthShift = (strokePaintStrokeWidth + strokeAccentPaintStrokeWidth) / 2.0f; float diagShift = orthShift / 1.41f; var path = new CGPath(); path.MoveToPoint(CG.Point(swipe % new SKPoint(center.X - radius, center.Y - radius))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius, center.Y - radius + 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 1 * step, center.Y - radius + 2 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius - 1 * step, center.Y - radius + 4 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 1 * step, center.Y - radius + 6 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius - 1 * step, center.Y - radius + 8 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 1 * step, center.Y - radius + 10 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius - 1 * step, center.Y - radius + 12 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius, center.Y - radius + 13 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius, center.Y + radius))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 1 * step, center.Y + radius))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 2 * step, center.Y + radius - 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 4 * step, center.Y + radius + 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 6 * step, center.Y + radius - 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 8 * step, center.Y + radius + 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 10 * step, center.Y + radius - 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 12 * step, center.Y + radius + 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + 13 * step, center.Y + radius))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius, center.Y + radius))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius, center.Y + radius - 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 1 * step, center.Y + radius - 2 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + 1 * step, center.Y + radius - 4 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 1 * step, center.Y + radius - 6 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + 1 * step, center.Y + radius - 8 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 1 * step, center.Y + radius - 10 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + 1 * step, center.Y + radius - 12 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius, center.Y + radius - 13 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius, center.Y - radius))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 1 * step, center.Y - radius))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 2 * step, center.Y - radius + 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 4 * step, center.Y - radius - 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 6 * step, center.Y - radius + 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 8 * step, center.Y - radius - 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 10 * step, center.Y - radius + 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 12 * step, center.Y - radius - 1 * step))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius - 13 * step, center.Y - radius))); path.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius, center.Y - radius))); path.CloseSubpath(); var accPathLft = new CGPath(); accPathLft.MoveToPoint(CG.Point(swipe % new SKPoint(center.X - radius + orthShift, center.Y - radius + orthShift))); accPathLft.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + orthShift, center.Y - radius + orthShift + 1 * step))); accPathLft.MoveToPoint(CG.Point(swipe % new SKPoint(center.X - radius + diagShift + 1 * step, center.Y - radius + diagShift + 2 * step))); accPathLft.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + diagShift - 1 * step, center.Y - radius + diagShift + 4 * step))); accPathLft.MoveToPoint(CG.Point(swipe % new SKPoint(center.X - radius + diagShift + 1 * step, center.Y - radius + diagShift + 6 * step))); accPathLft.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + diagShift - 1 * step, center.Y - radius + diagShift + 8 * step))); accPathLft.MoveToPoint(CG.Point(swipe % new SKPoint(center.X - radius + diagShift + 1 * step, center.Y - radius + diagShift + 10 * step))); accPathLft.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + diagShift - 1 * step, center.Y - radius + diagShift + 12 * step))); accPathLft.MoveToPoint(CG.Point(swipe % new SKPoint(center.X - radius + orthShift, center.Y - radius + 13 * step))); accPathLft.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X - radius + orthShift, center.Y - radius + 14 * step))); var accPathTop = new CGPath(); accPathTop.MoveToPoint(CG.Point(swipe % new SKPoint(center.X + radius, center.Y - radius + orthShift))); accPathTop.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + diagShift / 2 - 1 * step, center.Y - radius + orthShift))); accPathTop.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + diagShift - 2 * step, center.Y - radius + diagShift + 1 * step))); accPathTop.MoveToPoint(CG.Point(swipe % new SKPoint(center.X + radius + diagShift - 4 * step, center.Y - radius + diagShift - 1 * step))); accPathTop.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + diagShift - 6 * step, center.Y - radius + diagShift + 1 * step))); accPathTop.MoveToPoint(CG.Point(swipe % new SKPoint(center.X + radius + diagShift - 8 * step, center.Y - radius + diagShift - 1 * step))); accPathTop.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + diagShift - 10 * step, center.Y - radius + diagShift + 1 * step))); accPathTop.MoveToPoint(CG.Point(swipe % new SKPoint(center.X + radius + diagShift - 12 * step, center.Y - radius + diagShift - 1 * step))); accPathTop.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + diagShift / 2 - 13 * step, center.Y - radius + orthShift))); accPathTop.AddLineToPoint(CG.Point(swipe % new SKPoint(center.X + radius + orthShift - 14 * step, center.Y - radius + orthShift))); canvas.AddPath(path); canvas.SetFillColor(CG.Color(fillPaint.Color)); canvas.FillPath(); canvas.AddPath(accPathLft); canvas.SetStrokeColor(CG.Color(strokeAccentPaint.Color)); canvas.SetLineWidth(strokeAccentPaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(strokeAccentPaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(strokeAccentPaint.StrokeCap)); canvas.StrokePath(); canvas.AddPath(accPathTop); canvas.SetStrokeColor(CG.Color(strokeAccentPaint.Color)); canvas.SetLineWidth(strokeAccentPaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(strokeAccentPaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(strokeAccentPaint.StrokeCap)); canvas.StrokePath(); canvas.AddPath(path); canvas.SetStrokeColor(CG.Color(strokePaint.Color)); canvas.SetLineWidth(strokePaint.StrokeWidth); canvas.SetLineJoin(CG.LineJoin(strokePaint.StrokeJoin)); canvas.SetLineCap(CG.LineCap(strokePaint.StrokeCap)); canvas.StrokePath(); canvas.AddEllipseInRect(CG.RectFromCircle(swipe % new SKPoint(center.X + diagShift / 2, center.Y + diagShift / 2), swipe % (holeRadius + diagShift / 2))); canvas.SetFillColor(CG.Color(holeAccentPaint.Color)); canvas.FillPath(); canvas.AddEllipseInRect(CG.RectFromCircle(swipe % center, swipe % holeRadius)); canvas.SetFillColor(CG.Color(holePaint.Color)); canvas.FillPath(); }