private void DrawBackground() { var layerName = "backgroundLayer"; // Remove previous background layer if any var prevBackgroundLayer = _actualView.Layer.Sublayers?.FirstOrDefault(x => x.Name == layerName); prevBackgroundLayer?.RemoveFromSuperLayer(); NSBezierPath cornerPath = null; if (Element.Sides != 4) { cornerPath = Bounds.CreatePolygonPath(Element.Sides, Element.CornerRadius.TopLeft, Element.OffsetAngle); } else { cornerPath = Bounds.CreateRoundedRectPath(Element.CornerRadius); } // The layer used to mask other layers we draw on the background. var maskLayer = new CAShapeLayer { Frame = Bounds, Path = cornerPath.ToCGPath() }; _actualView.Layer.Mask = maskLayer; _actualView.Layer.MasksToBounds = true; if (Element.BackgroundGradientStops != null && Element.BackgroundGradientStops.Any()) { // Create a gradient layer that draws our background. var gradientLayer = CreateGradientLayer(Element.BackgroundGradientStartPoint, Element.BackgroundGradientEndPoint, Bounds); gradientLayer.Name = layerName; // A range of colors is given. Let's add them. var orderedStops = Element.BackgroundGradientStops.OrderBy(x => x.Offset).ToList(); gradientLayer.Colors = orderedStops.Select(x => x.Color.ToCGColor()).ToArray(); gradientLayer.Locations = orderedStops.Select(x => new NSNumber(x.Offset)).ToArray(); AddLayer(gradientLayer, 0, _actualView); } else { // Create a shape layer that draws our background. var shapeLayer = new CAShapeLayer { Frame = Bounds, Path = cornerPath.ToCGPath(), MasksToBounds = true, FillColor = _colorToRender.CGColor, Name = layerName }; AddLayer(shapeLayer, 0, _actualView); } }
CGPath?GetRoundedPath(CGRect rect, nfloat left, nfloat top, nfloat right, nfloat bottom) { #if __IOS__ var path = new UIBezierPath(); #else var path = new NSBezierPath(); #endif path.MoveTo(new CGPoint(rect.Width - right, rect.Y)); path.AddArc(new CGPoint((float)rect.X + rect.Width - right, (float)rect.Y + right), (nfloat)right, (float)(Math.PI * 1.5), (float)Math.PI * 2, true); path.AddLineTo(new CGPoint(rect.Width, rect.Height - bottom)); path.AddArc(new CGPoint((float)rect.X + rect.Width - bottom, (float)rect.Y + rect.Height - bottom), (nfloat)bottom, 0, (float)(Math.PI * .5), true); path.AddLineTo(new CGPoint(left, rect.Height)); path.AddArc(new CGPoint((float)rect.X + left, (float)rect.Y + rect.Height - left), (nfloat)left, (float)(Math.PI * .5), (float)Math.PI, true); path.AddLineTo(new CGPoint(rect.X, top)); path.AddArc(new CGPoint((float)rect.X + top, (float)rect.Y + top), (nfloat)top, (float)Math.PI, (float)(Math.PI * 1.5), true); path.ClosePath(); #if __IOS__ return(path.CGPath); #else return(path.ToCGPath()); #endif }
public static CAShapeLayer ToShape(this LinePath element) { var line = new CAShapeLayer(); var bezierPath = new NSBezierPath(); bezierPath.MoveTo(new CGPoint(element.X1, element.Y1)); bezierPath.LineTo(new CGPoint(element.X2, element.Y2)); line.Path = bezierPath.ToCGPath(); if (!string.IsNullOrEmpty(element.Stroke)) { line.StrokeColor = XExtensions.ConvertToNSColor(element.Stroke).CGColor; } if (!string.IsNullOrEmpty(element.Fill)) { line.FillColor = XExtensions.ConvertToNSColor(element.Fill).CGColor; } line.LineWidth = element.StrokeWidth; var width = Math.Max(element.X1, element.X2) - Math.Min(element.X1, element.X2); var height = Math.Max(element.Y1, element.Y2) - Math.Min(element.Y1, element.Y2); line.Bounds = new CGRect(0, 0, width, height); return(line); }
public override void UpdateLayer() { Layer.BackgroundColor = NSColor.FromRgb(245, 245, 245).CGColor; if (arrowLayers != null) { arrowLayers.ForEach(layer => layer.RemoveFromSuperLayer()); } arrowLayers = new List <CAShapeLayer> (); nfloat lastX = 8; var lastItem = items [items.Count - 1]; foreach (var item in items) { item.Layer.Position = new CGPoint(lastX, Bounds.GetMidY() - 1); lastX += item.Layer.Frame.Width + 20; if (item.Equals(lastItem)) { continue; } var arrow = new CAShapeLayer(); var path = new NSBezierPath(); path.MoveTo(new CGPoint(item.Layer.Frame.Right + 5, Bounds.Height)); path.LineTo(new CGPoint(item.Layer.Frame.Right + 15, Bounds.GetMidY())); path.LineTo(new CGPoint(item.Layer.Frame.Right + 5, 0)); arrow.ContentsScale = NSScreen.MainScreen.BackingScaleFactor; arrow.Path = path.ToCGPath(false); arrow.FillColor = null; arrow.StrokeColor = NSColor.FromWhite(0.85f, 1.0f).CGColor; arrowLayers.Add(arrow); Layer.AddSublayer(arrow); } }
public static NSImage ToTransformedCorners(NSImage source, double topLeftCornerSize, double topRightCornerSize, double bottomLeftCornerSize, double bottomRightCornerSize, CornerTransformType cornersTransformType, double cropWidthRatio, double cropHeightRatio) { double sourceWidth = source.CGImage.Width; double sourceHeight = source.CGImage.Height; double desiredWidth = sourceWidth; double desiredHeight = sourceHeight; double desiredRatio = cropWidthRatio / cropHeightRatio; double currentRatio = sourceWidth / sourceHeight; if (currentRatio > desiredRatio) { desiredWidth = (cropWidthRatio * sourceHeight / cropHeightRatio); } else if (currentRatio < desiredRatio) { desiredHeight = (cropHeightRatio * sourceWidth / cropWidthRatio); } topLeftCornerSize = topLeftCornerSize * (desiredWidth + desiredHeight) / 2 / 100; topRightCornerSize = topRightCornerSize * (desiredWidth + desiredHeight) / 2 / 100; bottomLeftCornerSize = bottomLeftCornerSize * (desiredWidth + desiredHeight) / 2 / 100; bottomRightCornerSize = bottomRightCornerSize * (desiredWidth + desiredHeight) / 2 / 100; float cropX = (float)((sourceWidth - desiredWidth) / 2); float cropY = (float)((sourceHeight - desiredHeight) / 2); var colorSpace = CGColorSpace.CreateDeviceRGB(); const int bytesPerPixel = 4; int width = (int)desiredWidth; int height = (int)desiredHeight; var bytes = new byte[width * height * bytesPerPixel]; int bytesPerRow = bytesPerPixel * width; const int bitsPerComponent = 8; using (var context = new CGBitmapContext(bytes, width, height, bitsPerComponent, bytesPerRow, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big)) { context.BeginPath(); using (var path = new NSBezierPath()) { // TopLeft if (cornersTransformType.HasFlag(CornerTransformType.TopLeftCut)) { path.MoveTo(new CGPoint(0, topLeftCornerSize)); path.LineTo(new CGPoint(topLeftCornerSize, 0)); } else if (cornersTransformType.HasFlag(CornerTransformType.TopLeftRounded)) { path.MoveTo(new CGPoint(0, topLeftCornerSize)); path.QuadCurveToPoint(new CGPoint(topLeftCornerSize, 0), new CGPoint(0, 0)); } else { path.MoveTo(new CGPoint(0, 0)); } // TopRight if (cornersTransformType.HasFlag(CornerTransformType.TopRightCut)) { path.LineTo(new CGPoint(desiredWidth - topRightCornerSize, 0)); path.LineTo(new CGPoint(desiredWidth, topRightCornerSize)); } else if (cornersTransformType.HasFlag(CornerTransformType.TopRightRounded)) { path.LineTo(new CGPoint(desiredWidth - topRightCornerSize, 0)); path.QuadCurveToPoint(new CGPoint(desiredWidth, topRightCornerSize), new CGPoint(desiredWidth, 0)); } else { path.LineTo(new CGPoint(desiredWidth, 0)); } // BottomRight if (cornersTransformType.HasFlag(CornerTransformType.BottomRightCut)) { path.LineTo(new CGPoint(desiredWidth, desiredHeight - bottomRightCornerSize)); path.LineTo(new CGPoint(desiredWidth - bottomRightCornerSize, desiredHeight)); } else if (cornersTransformType.HasFlag(CornerTransformType.BottomRightRounded)) { path.LineTo(new CGPoint(desiredWidth, desiredHeight - bottomRightCornerSize)); path.QuadCurveToPoint(new CGPoint(desiredWidth - bottomRightCornerSize, desiredHeight), new CGPoint(desiredWidth, desiredHeight)); } else { path.LineTo(new CGPoint(desiredWidth, desiredHeight)); } // BottomLeft if (cornersTransformType.HasFlag(CornerTransformType.BottomLeftCut)) { path.LineTo(new CGPoint(bottomLeftCornerSize, desiredHeight)); path.LineTo(new CGPoint(0, desiredHeight - bottomLeftCornerSize)); } else if (cornersTransformType.HasFlag(CornerTransformType.BottomLeftRounded)) { path.LineTo(new CGPoint(bottomLeftCornerSize, desiredHeight)); path.QuadCurveToPoint(new CGPoint(0, desiredHeight - bottomLeftCornerSize), new CGPoint(0, desiredHeight)); } else { path.LineTo(new CGPoint(0, desiredHeight)); } path.ClosePath(); context.AddPath(path.ToCGPath()); context.Clip(); } var drawRect = new CGRect(-cropX, -cropY, sourceWidth, sourceHeight); context.DrawImage(drawRect, source.CGImage); using (var output = context.ToImage()) { return(new NSImage(output, CGSize.Empty)); } } }