/// <summary> /// Fills the cache with bitmaps for the given dataset. /// </summary> protected void Fill(DataSetImageCache cache, ILineDataSet set, bool drawCircleHole, bool drawTransparentCircleHole) { int colorCount = set.CircleColorCount; float circleRadius = set.CircleRadius; float circleHoleRadius = set.CircleHoleRadius; var circleBitmaps = cache.CircleBitmaps; var circlePath = cache.CirclePathBuffer; for (int i = 0; i < colorCount; i++) { var circleBitmap = new SKBitmap((int)(circleRadius * 2.1), (int)(circleRadius * 2.1)); var canvas = new SKCanvas(circleBitmap); circleBitmaps[i] = circleBitmap; RenderPaint.Color = set.GetCircleColor(i); if (drawTransparentCircleHole) { // Begin path for circle with hole circlePath.Reset(); circlePath.AddCircle( circleRadius, circleRadius, circleRadius, SKPathDirection.Clockwise); // Cut hole in path circlePath.AddCircle( circleRadius, circleRadius, circleHoleRadius, SKPathDirection.CounterClockwise); // Fill in-between canvas.DrawPath(circlePath, RenderPaint); } else { canvas.DrawCircle( circleRadius, circleRadius, circleRadius, RenderPaint); if (drawCircleHole) { canvas.DrawCircle( circleRadius, circleRadius, circleHoleRadius, CirclePaintInner); } } } }
protected void DrawCircles(SKCanvas c) { RenderPaint.Style = SKPaintStyle.Fill; float phaseY = Animator.PhaseY; var dataSets = ((Interfaces.DataProvider.ILineChartProvider)Chart).Data.DataSets; for (int i = 0; i < dataSets.Count; i++) { ILineDataSet dataSet = dataSets[i]; if (!dataSet.IsVisible || !dataSet.IsDrawCirclesEnabled || dataSet.EntryCount == 0) { continue; } CirclePaintInner.Color = dataSet.CircleHoleColor; Transformer trans = Chart.GetTransformer(dataSet.AxisDependency); XBounds.Set(Chart, dataSet, Animator); float circleRadius = dataSet.CircleRadius; float circleHoleRadius = dataSet.CircleHoleRadius; var drawCircleHole = dataSet.IsDrawCircleHoleEnabled && circleHoleRadius <circleRadius && circleHoleRadius> 0.0f; var drawTransparentCircleHole = drawCircleHole && dataSet.CircleHoleColor == SKColors.Empty; if (imageCaches.TryGetValue(dataSet, out DataSetImageCache imageCache) == false) { imageCache = new DataSetImageCache(); imageCaches.Add(dataSet, imageCache); } // only fill the cache with new bitmaps if a change is required if (imageCache.Init(dataSet)) { Fill(imageCache, dataSet, drawCircleHole, drawTransparentCircleHole); } int boundsRangeCount = XBounds.Range + XBounds.Min; for (int j = XBounds.Min; j <= boundsRangeCount; j++) { Entry e = ((IDataSet)dataSet)[j]; if (e == null) { break; } var pt = trans.PointValueToPixel(e.X, e.Y * phaseY); if (!ViewPortHandler.IsInBoundsRight(pt.X)) { break; } if (!ViewPortHandler.IsInBoundsLeft(pt.X) || !ViewPortHandler.IsInBoundsY(pt.Y)) { continue; } var circleBitmap = imageCache.GetBitmap(j); if (circleBitmap != null) { c.DrawBitmap(circleBitmap, pt.X - circleRadius, pt.Y - circleRadius, null); } } } }