Skip to content

Commit 57e8a9b

Browse files
committed
fix: correctly draw fill per x
In the process i refactored to only create circlebuffer when needed We should start to do that everywhere
1 parent 311f6dc commit 57e8a9b

File tree

1 file changed

+52
-28
lines changed

1 file changed

+52
-28
lines changed

src/charting/renderer/LineChartRenderer.ts

+52-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Canvas, Direction, FillType, Matrix, Paint, Path, Style, createImage, releaseImage } from '@nativescript-community/ui-canvas';
2-
import { ImageSource, profile } from '@nativescript/core';
2+
import { Color, ImageSource, profile } from '@nativescript/core';
33
import { ChartAnimator } from '../animation/ChartAnimator';
44
import { LineChart } from '../charts';
55
import { getEntryXValue } from '../data/BaseEntry';
@@ -124,6 +124,23 @@ export class LineChartRenderer extends LineRadarRenderer {
124124
protected linePath = new Path();
125125
protected fillPath = new Path();
126126

127+
/**
128+
* cache for the circle bitmaps of all datasets
129+
*/
130+
private mImageCaches = new Map<ILineDataSet, DataSetImageCache>();
131+
132+
/**
133+
* buffer for drawing the circles
134+
*/
135+
private mCirclesBuffer: [number, number];
136+
137+
private get circlesBuffer() {
138+
if (!this.mCirclesBuffer) {
139+
this.mCirclesBuffer = Utils.createNativeArray(2);
140+
}
141+
return this.mCirclesBuffer;
142+
}
143+
127144
constructor(chart: LineChart, animator: ChartAnimator, viewPortHandler: ViewPortHandler) {
128145
super(animator, viewPortHandler);
129146
this.mChart = chart;
@@ -137,7 +154,7 @@ export class LineChartRenderer extends LineRadarRenderer {
137154
this.mCirclePaintInner.setColor('white');
138155
}
139156

140-
public initBuffers() { }
157+
public initBuffers() {}
141158

142159
@profile
143160
public drawData(c: Canvas) {
@@ -539,12 +556,23 @@ export class LineChartRenderer extends LineRadarRenderer {
539556
lastDrawnIndex -= 1;
540557
}
541558
}
559+
let fillMin = drawFilled && useColorsForFill ? dataSet.getFillFormatter().getFillLinePosition(dataSet, this.mChart) : undefined;
560+
if (fillMin !== undefined) {
561+
// to make things faster we wont transform the path again
562+
// so we need get fillMin as pixel value
563+
// let's use circlesBuffer for this
564+
const circleBuffer = this.circlesBuffer;
565+
circleBuffer[0] = 0;
566+
circleBuffer[1] = fillMin;
567+
trans.pointValuesToPixel(circleBuffer);
568+
fillMin = circleBuffer[1];
569+
}
542570
colorsToBeDrawn.forEach((color) => {
543571
this.linePath.setLines(points, color.startIndex * 2, color.nbItems * 2);
544572
if (drawFilled && useColorsForFill) {
545573
this.fillPath.reset();
546574
this.fillPath.addPath(this.linePath);
547-
this.drawFill(c, dataSet, this.fillPath, null, points[color.startIndex * 2], points[(color.startIndex + color.nbItems - 1) * 2], color);
575+
this.drawFill(c, dataSet, this.fillPath, null, points[color.startIndex * 2], points[(color.startIndex + color.nbItems - 1) * 2], color.color, fillMin);
548576
}
549577
if (drawLine) {
550578
this.mRenderPaint.setColor(color.color);
@@ -565,9 +593,10 @@ export class LineChartRenderer extends LineRadarRenderer {
565593
}
566594
}
567595

568-
protected drawFill(c: Canvas, dataSet: ILineDataSet, spline: Path, trans: Transformer, min: number, max: number, color?) {
569-
const fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, this.mChart);
570-
596+
protected drawFill(c: Canvas, dataSet: ILineDataSet, spline: Path, trans: Transformer, min: number, max: number, color?, fillMin?: number) {
597+
if (fillMin === undefined) {
598+
fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, this.mChart);
599+
}
571600
spline.lineTo(max, fillMin);
572601
spline.lineTo(min, fillMin);
573602
spline.close();
@@ -656,16 +685,6 @@ export class LineChartRenderer extends LineRadarRenderer {
656685
this.drawCircles(c);
657686
}
658687

659-
/**
660-
* cache for the circle bitmaps of all datasets
661-
*/
662-
private mImageCaches = new Map<ILineDataSet, DataSetImageCache>();
663-
664-
/**
665-
* buffer for drawing the circles
666-
*/
667-
private mCirclesBuffer = Utils.createNativeArray(2);
668-
669688
@profile
670689
protected drawCirclesForDataset(c: Canvas, dataSet: LineDataSet) {
671690
this.mCirclePaintInner.setColor(dataSet.getCircleHoleColor());
@@ -699,36 +718,41 @@ export class LineChartRenderer extends LineRadarRenderer {
699718
}
700719

701720
const boundsRangeCount = this.mXBounds.range + this.mXBounds.min;
702-
721+
const circleBuffer = this.circlesBuffer;
703722
for (let j = this.mXBounds.min; j <= boundsRangeCount; j++) {
704723
const e = dataSet.getEntryForIndex(j);
705724

706725
if (e == null) continue;
707726

708-
this.mCirclesBuffer[0] = getEntryXValue(e, xKey, j);
709-
this.mCirclesBuffer[1] = e[yKey] * phaseY;
727+
circleBuffer[0] = getEntryXValue(e, xKey, j);
728+
circleBuffer[1] = e[yKey] * phaseY;
710729

711-
trans.pointValuesToPixel(this.mCirclesBuffer);
730+
trans.pointValuesToPixel(circleBuffer);
731+
// native buffer access is slow
732+
const cx = circleBuffer[0];
733+
const cy = circleBuffer[1];
712734

713-
if (!this.mViewPortHandler.isInBoundsRight(this.mCirclesBuffer[0])) break;
735+
if (!this.mViewPortHandler.isInBoundsRight(cx)) break;
714736

715-
if (!this.mViewPortHandler.isInBoundsLeft(this.mCirclesBuffer[0]) || !this.mViewPortHandler.isInBoundsY(this.mCirclesBuffer[1])) continue;
737+
if (!this.mViewPortHandler.isInBoundsLeft(cx) || !this.mViewPortHandler.isInBoundsY(cy)) continue;
716738

717739
const circleBitmap = imageCache.getBitmap(j);
718740

719741
if (circleBitmap != null) {
720-
c.drawBitmap(circleBitmap, this.mCirclesBuffer[0] - circleRadius, this.mCirclesBuffer[1] - circleRadius, null);
742+
c.drawBitmap(circleBitmap, cx - circleRadius, cy - circleRadius, null);
721743
}
722744
}
723745
}
724746

725747
protected drawCircles(c: Canvas) {
726-
this.mRenderPaint.setStyle(Style.FILL);
727-
728-
this.mCirclesBuffer[0] = 0;
729-
this.mCirclesBuffer[1] = 0;
730-
731748
const dataSets = this.mChart.getLineData().getVisibleDataSets();
749+
if (dataSets.some((d) => d.isDrawCirclesEnabled()) === false) {
750+
return;
751+
}
752+
this.mRenderPaint.setStyle(Style.FILL);
753+
const circleBuffer = this.circlesBuffer;
754+
circleBuffer[0] = 0;
755+
circleBuffer[1] = 0;
732756

733757
for (let i = 0; i < dataSets.length; i++) {
734758
const dataSet = dataSets[i];

0 commit comments

Comments
 (0)