public override Carto.Graphics.Bitmap OnDrawPopup(PopupDrawInfo popupDrawInfo) { PopupStyle style = popupDrawInfo.Popup.Style; // Calculate scaled dimensions float DPToPX = popupDrawInfo.DPToPX; float PXTODP = 1 / DPToPX; if (style.ScaleWithDPI) { DPToPX = 1; } else { PXTODP = 1; } float screenWidth = popupDrawInfo.ScreenBounds.GetWidth() * PXTODP; float screenHeight = popupDrawInfo.ScreenBounds.GetHeight() * PXTODP; // Update sizes based on scale (uses extension method, cf. Shared/Extensions int fontSize = FontSize.Update(DPToPX); int triangleWidth = TriangleSize.Update(DPToPX); int triangleHeight = TriangleSize.Update(DPToPX); int strokeWidth = StrokeWidth.Update(DPToPX); int screenPadding = ScreenPadding.Update(DPToPX); // Set font var font = Android.Graphics.Typeface.Create("HelveticaNeue-Light", Android.Graphics.TypefaceStyle.Normal); // Calculate the maximum popup size, adjust with dpi int maxPopupWidth = (int)(Math.Min(screenWidth, screenHeight)); float halfStrokeWidth = strokeWidth * 0.5f; int maxTextWidth = maxPopupWidth - (2 * screenPadding + strokeWidth); // Measure text TextPaint textPaint = new TextPaint { Color = TextColor, TextSize = fontSize }; textPaint.SetTypeface(font); var textLayout = new StaticLayout(text, textPaint, maxTextWidth, Layout.Alignment.AlignNormal, 1, 0, false); int textX = (int)Math.Min(textPaint.MeasureText(text), textLayout.Width); int textY = textLayout.Height; int popupWidth = textX + (2 * PopupPadding + strokeWidth + triangleWidth); int popupHeight = textY + (2 * PopupPadding + strokeWidth); var bitmap = Android.Graphics.Bitmap.CreateBitmap(popupWidth, popupHeight, Android.Graphics.Bitmap.Config.Argb8888); var canvas = new Android.Graphics.Canvas(bitmap); var trianglePath = new Android.Graphics.Path(); trianglePath.MoveTo(triangleWidth, 0); trianglePath.LineTo(halfStrokeWidth, triangleHeight * 0.5f); trianglePath.LineTo(triangleWidth, triangleHeight); trianglePath.Close(); int triangleOffsetX = 0; int triangleOffsetY = (popupHeight - triangleHeight) / 2; // Create paint object var paint = new Android.Graphics.Paint(); paint.AntiAlias = true; paint.SetStyle(Android.Graphics.Paint.Style.Stroke); paint.StrokeWidth = strokeWidth; paint.Color = StrokeColor; // Stroke background var background = new Android.Graphics.RectF(); background.Left = triangleWidth; background.Top = halfStrokeWidth; background.Right = popupWidth - strokeWidth; background.Bottom = popupHeight - strokeWidth; canvas.DrawRect(background, paint); // Stroke triangle canvas.Save(); canvas.Translate(triangleOffsetX, triangleOffsetY); canvas.DrawPath(trianglePath, paint); canvas.Restore(); // Fill background paint.SetStyle(Android.Graphics.Paint.Style.Fill); paint.Color = BackgroundColor; canvas.DrawRect(background, paint); // Fill triangle canvas.Save(); canvas.Translate(triangleOffsetX, triangleOffsetY); canvas.DrawPath(trianglePath, paint); canvas.Restore(); if (textLayout != null) { // Draw text canvas.Save(); canvas.Translate(halfStrokeWidth + triangleWidth + PopupPadding, halfStrokeWidth + PopupPadding); textLayout.Draw(canvas); canvas.Restore(); } return BitmapUtils.CreateBitmapFromAndroidBitmap(bitmap); }
public static void SmoothedPathWithGranularity(List <NativePoint> currentPoints, int granularity, out NativePath smoothedPath, out List <NativePoint> smoothedPoints) { // not enough points to smooth effectively, so return the original path and points. if (currentPoints.Count < 4) { smoothedPath = null; smoothedPoints = null; return; } // create a new bezier path to hold the smoothed path. smoothedPath = new NativePath(); smoothedPoints = new List <NativePoint> (); // duplicate the first and last points as control points. currentPoints.Insert(0, currentPoints[0]); currentPoints.Add(currentPoints[currentPoints.Count - 1]); // add the first point smoothedPath.MoveTo(currentPoints[0].X, currentPoints[0].Y); smoothedPoints.Add(currentPoints[0]); for (var index = 1; index < currentPoints.Count - 2; index++) { var p0 = currentPoints[index - 1]; var p1 = currentPoints[index]; var p2 = currentPoints[index + 1]; var p3 = currentPoints[index + 2]; // add n points starting at p1 + dx/dy up until p2 using Catmull-Rom splines for (var i = 1; i < granularity; i++) { var t = (float)i * (1f / (float)granularity); var tt = t * t; var ttt = tt * t; // intermediate point var mid = new NativePoint { X = 0.5f * (2f * p1.X + (p2.X - p0.X) * t + (2f * p0.X - 5f * p1.X + 4f * p2.X - p3.X) * tt + (3f * p1.X - p0.X - 3f * p2.X + p3.X) * ttt), Y = 0.5f * (2 * p1.Y + (p2.Y - p0.Y) * t + (2 * p0.Y - 5 * p1.Y + 4 * p2.Y - p3.Y) * tt + (3 * p1.Y - p0.Y - 3 * p2.Y + p3.Y) * ttt) }; smoothedPath.LineTo(mid.X, mid.Y); smoothedPoints.Add(mid); } // add p2 smoothedPath.LineTo(p2.X, p2.Y); smoothedPoints.Add(p2); } // add the last point var last = currentPoints[currentPoints.Count - 1]; smoothedPath.LineTo(last.X, last.Y); smoothedPoints.Add(last); }
public override Carto.Graphics.Bitmap OnDrawPopup(PopupDrawInfo popupDrawInfo) { PopupStyle style = popupDrawInfo.Popup.Style; // Calculate scaled dimensions float DPToPX = popupDrawInfo.DPToPX; float PXTODP = 1 / DPToPX; if (style.ScaleWithDPI) { DPToPX = 1; } else { PXTODP = 1; } float screenWidth = popupDrawInfo.ScreenBounds.GetWidth() * PXTODP; float screenHeight = popupDrawInfo.ScreenBounds.GetHeight() * PXTODP; // Update sizes based on scale (uses extension method, cf. Shared/Extensions int fontSize = FontSize.Update(DPToPX); int triangleWidth = TriangleSize.Update(DPToPX); int triangleHeight = TriangleSize.Update(DPToPX); int strokeWidth = StrokeWidth.Update(DPToPX); int screenPadding = ScreenPadding.Update(DPToPX); // Set font var font = Android.Graphics.Typeface.Create("HelveticaNeue-Light", Android.Graphics.TypefaceStyle.Normal); // Calculate the maximum popup size, adjust with dpi int maxPopupWidth = (int)(Math.Min(screenWidth, screenHeight)); float halfStrokeWidth = strokeWidth * 0.5f; int maxTextWidth = maxPopupWidth - (2 * screenPadding + strokeWidth); // Measure text TextPaint textPaint = new TextPaint { Color = TextColor, TextSize = fontSize }; textPaint.SetTypeface(font); var textLayout = new StaticLayout(text, textPaint, maxTextWidth, Layout.Alignment.AlignNormal, 1, 0, false); int textX = (int)Math.Min(textPaint.MeasureText(text), textLayout.Width); int textY = textLayout.Height; int popupWidth = textX + (2 * PopupPadding + strokeWidth + triangleWidth); int popupHeight = textY + (2 * PopupPadding + strokeWidth); var bitmap = Android.Graphics.Bitmap.CreateBitmap(popupWidth, popupHeight, Android.Graphics.Bitmap.Config.Argb8888); var canvas = new Android.Graphics.Canvas(bitmap); var trianglePath = new Android.Graphics.Path(); trianglePath.MoveTo(triangleWidth, 0); trianglePath.LineTo(halfStrokeWidth, triangleHeight * 0.5f); trianglePath.LineTo(triangleWidth, triangleHeight); trianglePath.Close(); int triangleOffsetX = 0; int triangleOffsetY = (popupHeight - triangleHeight) / 2; // Create paint object var paint = new Android.Graphics.Paint(); paint.AntiAlias = true; paint.SetStyle(Android.Graphics.Paint.Style.Stroke); paint.StrokeWidth = strokeWidth; paint.Color = StrokeColor; // Stroke background var background = new Android.Graphics.RectF(); background.Left = triangleWidth; background.Top = halfStrokeWidth; background.Right = popupWidth - strokeWidth; background.Bottom = popupHeight - strokeWidth; canvas.DrawRect(background, paint); // Stroke triangle canvas.Save(); canvas.Translate(triangleOffsetX, triangleOffsetY); canvas.DrawPath(trianglePath, paint); canvas.Restore(); // Fill background paint.SetStyle(Android.Graphics.Paint.Style.Fill); paint.Color = BackgroundColor; canvas.DrawRect(background, paint); // Fill triangle canvas.Save(); canvas.Translate(triangleOffsetX, triangleOffsetY); canvas.DrawPath(trianglePath, paint); canvas.Restore(); if (textLayout != null) { // Draw text canvas.Save(); canvas.Translate(halfStrokeWidth + triangleWidth + PopupPadding, halfStrokeWidth + PopupPadding); textLayout.Draw(canvas); canvas.Restore(); } return(BitmapUtils.CreateBitmapFromAndroidBitmap(bitmap)); }
public void FillPolygon(Brush brush, Point[] points) { APaint.Color = brush.Color.AColor(); APaint.Flags = (Android.Graphics.PaintFlags)0; APaint.Flags = Flags; APaint.SetStyle(Android.Graphics.Paint.Style.Fill); APaint.StrokeWidth = LineWidth; var p = new Android.Graphics.Path(); p.MoveTo(points[0].X, points[0].Y); foreach(var pt in points) p.LineTo(pt.X, pt.Y); ACanvas.DrawPath(p, APaint); p.Dispose(); }
public void UpdateData(APath path) { UpdateShape(path); }
/// <summary> /// Obtain a smoothed path with the specified granularity from the current path using Catmull-Rom spline. /// Also outputs a List of the points corresponding to the smoothed path. /// </summary> /// <remarks> /// Implemented using a modified version of the code in the solution at /// http://stackoverflow.com/questions/8702696/drawing-smooth-curves-methods-needed /// </remarks> public static InkStroke SmoothedPathWithGranularity(InkStroke currentPath, int granularity) { var currentPoints = currentPath.GetPoints().ToList(); // not enough points to smooth effectively, so return the original path and points. if (currentPoints.Count < 4) { return(currentPath); } // create a new bezier path to hold the smoothed path. var smoothedPath = new NativePath(); var smoothedPoints = new List <NativePoint> (); // duplicate the first and last points as control points. currentPoints.Insert(0, currentPoints[0]); currentPoints.Add(currentPoints[currentPoints.Count - 1]); // add the first point smoothedPath.MoveTo(currentPoints[0].X, currentPoints[0].Y); smoothedPoints.Add(currentPoints[0]); for (var index = 1; index < currentPoints.Count - 2; index++) { var p0 = currentPoints[index - 1]; var p1 = currentPoints[index]; var p2 = currentPoints[index + 1]; var p3 = currentPoints[index + 2]; // add n points starting at p1 + dx/dy up until p2 using Catmull-Rom splines for (var i = 1; i < granularity; i++) { var t = (float)i * (1f / (float)granularity); var tt = t * t; var ttt = tt * t; // intermediate point var mid = new NativePoint { X = 0.5f * (2f * p1.X + (p2.X - p0.X) * t + (2f * p0.X - 5f * p1.X + 4f * p2.X - p3.X) * tt + (3f * p1.X - p0.X - 3f * p2.X + p3.X) * ttt), Y = 0.5f * (2 * p1.Y + (p2.Y - p0.Y) * t + (2 * p0.Y - 5 * p1.Y + 4 * p2.Y - p3.Y) * tt + (3 * p1.Y - p0.Y - 3 * p2.Y + p3.Y) * ttt) }; smoothedPath.LineTo(mid.X, mid.Y); smoothedPoints.Add(mid); } // add p2 smoothedPath.LineTo(p2.X, p2.Y); smoothedPoints.Add(p2); } // add the last point var last = currentPoints[currentPoints.Count - 1]; smoothedPath.LineTo(last.X, last.Y); smoothedPoints.Add(last); // create the new path with the old attributes #if __ANDROID__ || __IOS__ return(new InkStroke(smoothedPath, smoothedPoints.ToList(), currentPath.Color, currentPath.Width)); #elif WINDOWS_PHONE var da = currentPath.DrawingAttributes; smoothedPath.DrawingAttributes = new DrawingAttributes { Color = da.Color, OutlineColor = da.OutlineColor, Width = da.Width, Height = da.Height, }; return(smoothedPath); #elif WINDOWS_UWP var da = currentPath.DrawingAttributes; var builder = new InkStrokeBuilder(); builder.SetDefaultDrawingAttributes(new InkDrawingAttributes { Color = da.Color, Size = da.Size }); return(builder.CreateStroke(smoothedPath)); #endif }