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);
        }
Example #2
0
        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);
        }
Example #3
0
        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));
        }
Example #4
0
 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();
 }
Example #5
0
 public void UpdateData(APath path)
 {
     UpdateShape(path);
 }
Example #6
0
        /// <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
        }