导航菜单

页面标题

页面副标题

xDrip+ v04633772025.07.16 - LineChartRenderer.java 源代码

正在查看: xDrip+ v04633772025.07.16 应用的 LineChartRenderer.java JAVA 源代码文件

本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。


package lecho.lib.hellocharts.renderer;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.Log;
import java.util.HashMap;
import java.util.Iterator;
import lecho.lib.hellocharts.computator.ChartComputator;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.SelectedValue;
import lecho.lib.hellocharts.model.ValueShape;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.provider.LineChartDataProvider;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.Chart;

public class LineChartRenderer extends AbstractChartRenderer {
    private double baseValue;
    private int checkPrecision;
    private LineChartDataProvider dataProvider;
    private Paint linePaint;
    private final Path path;
    private Paint pointPaint;
    private Bitmap softwareBitmap;
    private Canvas softwareCanvas;
    private Viewport tempMaximumViewport;
    private int touchToleranceMargin;

    public LineChartRenderer(Context context, Chart chart, LineChartDataProvider lineChartDataProvider) {
        super(context, chart);
        this.path = new Path();
        this.linePaint = new Paint();
        this.pointPaint = new Paint();
        this.softwareCanvas = new Canvas();
        this.tempMaximumViewport = new Viewport();
        this.dataProvider = lineChartDataProvider;
        this.touchToleranceMargin = ChartUtils.dp2px(this.density, 4);
        this.linePaint.setAntiAlias(true);
        this.linePaint.setStyle(Paint.Style.STROKE);
        this.linePaint.setStrokeCap(Paint.Cap.ROUND);
        this.linePaint.setStrokeWidth(ChartUtils.dp2px(this.density, 3));
        this.pointPaint.setAntiAlias(true);
        this.pointPaint.setStyle(Paint.Style.FILL);
        this.checkPrecision = ChartUtils.dp2px(this.density, 2);
        preScaleBitmaps();
    }

    private void preScaleBitmaps() {
        LineChartData lineChartData = this.dataProvider.getLineChartData();
        if (lineChartData != null) {
            for (Line line : lineChartData.getLines()) {
                if (line.isBitmapLabels()) {
                    BitmapCacheProvider bitmapCacheProvider = line.getBitmapCacheProvider();
                    if (bitmapCacheProvider != null) {
                        for (PointValue pointValue : line.getValues()) {
                            if (pointValue.getLabelBitMapKey() != null && pointValue.getFinalLabelBitMapKey() == null) {
                                pointValue.setFinalLabelBitMapKey(bitmapCacheProvider.prepareScaledBitmap(pointValue.getLabelBitMapKey(), line.getBitmapScale() * pointValue.getBitmapScale()));
                            }
                        }
                    } else {
                        throw new RuntimeException("BitmapLabels set but no BitmapCacheProvider set");
                    }
                }
            }
        }
    }

    @Override
    public void onChartSizeChanged() {
        int calculateContentRectInternalMargin = calculateContentRectInternalMargin();
        this.computator.insetContentRectByInternalMargins(calculateContentRectInternalMargin, calculateContentRectInternalMargin, calculateContentRectInternalMargin, calculateContentRectInternalMargin);
        try {
            if (this.computator.getChartWidth() <= 0 || this.computator.getChartHeight() <= 0) {
                return;
            }
            Bitmap createBitmap = Bitmap.createBitmap(this.computator.getChartWidth(), this.computator.getChartHeight(), Bitmap.Config.ARGB_8888);
            this.softwareBitmap = createBitmap;
            this.softwareCanvas.setBitmap(createBitmap);
        } catch (IllegalArgumentException e) {
            Log.e("HELLOCHARTS", "IllegalArgumentException during onChartSizeChanged: " + e);
        } catch (NegativeArraySizeException e2) {
            Log.e("HELLOCHARTS", "NegativeArraySizeException during onChartSizeChanged: " + e2);
        }
    }

    @Override
    public void onChartDataChanged() {
        super.onChartDataChanged();
        int calculateContentRectInternalMargin = calculateContentRectInternalMargin();
        this.computator.insetContentRectByInternalMargins(calculateContentRectInternalMargin, calculateContentRectInternalMargin, calculateContentRectInternalMargin, calculateContentRectInternalMargin);
        this.baseValue = this.dataProvider.getLineChartData().getBaseValue();
        preScaleBitmaps();
        onChartViewportChanged();
    }

    @Override
    public void onChartViewportChanged() {
        if (this.isViewportCalculationEnabled) {
            calculateMaxViewport();
            this.computator.setMaxViewport(this.tempMaximumViewport);
            ChartComputator chartComputator = this.computator;
            chartComputator.setCurrentViewport(chartComputator.getMaximumViewport());
        }
    }

    @Override
    public void drawBackgroundUnclipped(Canvas canvas) {
        for (Line line : this.dataProvider.getLineChartData().getLines()) {
            if (line.isBackgroundUnclipped() && line.hasLines()) {
                if (line.isCubic()) {
                    drawSmoothPath(canvas, line);
                } else if (line.isSquare()) {
                    drawSquarePath(canvas, line);
                } else {
                    drawPath(canvas, line);
                }
            }
        }
    }

    @Override
    public void draw(Canvas canvas) {
        Canvas canvas2;
        LineChartData lineChartData = this.dataProvider.getLineChartData();
        if (this.softwareBitmap != null) {
            canvas2 = this.softwareCanvas;
            canvas2.drawColor(0, PorterDuff.Mode.CLEAR);
        } else {
            canvas2 = canvas;
        }
        for (Line line : lineChartData.getLines()) {
            if (line.hasLines() && !line.isBackgroundUnclipped()) {
                if (line.isCubic()) {
                    drawSmoothPath(canvas2, line);
                } else if (line.isSquare()) {
                    drawSquarePath(canvas2, line);
                } else {
                    drawPath(canvas2, line);
                }
            }
        }
        Bitmap bitmap = this.softwareBitmap;
        if (bitmap != null) {
            canvas.drawBitmap(bitmap, 0.0f, 0.0f, (Paint) null);
        }
    }

    @Override
    public void drawUnclipped(Canvas canvas) {
        int i = 0;
        for (Line line : this.dataProvider.getLineChartData().getLines()) {
            if (checkIfShouldDrawPoints(line)) {
                drawPoints(canvas, line, i, 0);
            }
            i++;
        }
        if (isTouched()) {
            highlightPoints(canvas);
        }
    }

    private boolean checkIfShouldDrawPoints(Line line) {
        return line.hasPoints() || line.getValues().size() == 1;
    }

    @Override
    public boolean checkTouch(double d, double d2) {
        this.selectedValue.clear();
        int i = 0;
        for (Line line : this.dataProvider.getLineChartData().getLines()) {
            if (checkIfShouldDrawPoints(line)) {
                int dp2px = ChartUtils.dp2px(this.density, line.getPointRadius());
                int i2 = 0;
                for (PointValue pointValue : line.getValues()) {
                    int i3 = i2;
                    if (isInArea(this.computator.computeRawX(pointValue.getX()), this.computator.computeRawY(pointValue.getY()), d, d2, this.touchToleranceMargin + dp2px)) {
                        this.selectedValue.set(i, i3, SelectedValue.SelectedValueType.LINE);
                    }
                    i2 = i3 + 1;
                }
            }
            i++;
        }
        return isTouched();
    }

    private void calculateMaxViewport() {
        this.tempMaximumViewport.set(Double.MAX_VALUE, Double.MIN_VALUE, Double.MIN_VALUE, Double.MAX_VALUE);
        Iterator<Line> it = this.dataProvider.getLineChartData().getLines().iterator();
        while (it.hasNext()) {
            for (PointValue pointValue : it.next().getValues()) {
                double x = pointValue.getX();
                Viewport viewport = this.tempMaximumViewport;
                if (x < viewport.left) {
                    viewport.left = pointValue.getX();
                }
                double x2 = pointValue.getX();
                Viewport viewport2 = this.tempMaximumViewport;
                if (x2 > viewport2.right) {
                    viewport2.right = pointValue.getX();
                }
                double y = pointValue.getY();
                Viewport viewport3 = this.tempMaximumViewport;
                if (y < viewport3.bottom) {
                    viewport3.bottom = pointValue.getY();
                }
                double y2 = pointValue.getY();
                Viewport viewport4 = this.tempMaximumViewport;
                if (y2 > viewport4.top) {
                    viewport4.top = pointValue.getY();
                }
            }
        }
    }

    private int calculateContentRectInternalMargin() {
        int pointRadius;
        int i = 0;
        for (Line line : this.dataProvider.getLineChartData().getLines()) {
            if (checkIfShouldDrawPoints(line) && (pointRadius = line.getPointRadius() + 4) > i) {
                i = pointRadius;
            }
        }
        return ChartUtils.dp2px(this.density, i);
    }

    private void drawPath(Canvas canvas, Line line) {
        prepareLinePaint(line);
        boolean isReverseYAxis = line.isReverseYAxis();
        int i = 0;
        for (PointValue pointValue : line.getValues()) {
            double computeRawX = this.computator.computeRawX(pointValue.getX());
            ChartComputator chartComputator = this.computator;
            double computeReverseRawYNoMargin = isReverseYAxis ? chartComputator.computeReverseRawYNoMargin(pointValue.getY()) : chartComputator.computeRawY(pointValue.getY());
            if (i == 0) {
                this.path.moveTo((float) computeRawX, (float) computeReverseRawYNoMargin);
            } else {
                this.path.lineTo((float) computeRawX, (float) computeReverseRawYNoMargin);
            }
            i++;
        }
        canvas.drawPath(this.path, this.linePaint);
        if (line.isFilled()) {
            drawArea(canvas, line);
        }
        this.path.reset();
    }

    private void drawSimplePath(Canvas canvas, PointValue pointValue, double d, double d2) {
        this.path.moveTo((float) this.computator.computeRawX(pointValue.getX()), (float) this.computator.computeRawY(pointValue.getY()));
        this.path.lineTo((float) this.computator.computeRawX(d), (float) this.computator.computeRawY(d2));
        canvas.drawPath(this.path, this.linePaint);
        this.path.reset();
    }

    private void drawSquarePath(Canvas canvas, Line line) {
        prepareLinePaint(line);
        boolean isReverseYAxis = line.isReverseYAxis();
        int i = 0;
        double d = 0.0d;
        for (PointValue pointValue : line.getValues()) {
            double computeRawX = this.computator.computeRawX(pointValue.getX());
            ChartComputator chartComputator = this.computator;
            double computeReverseRawYNoMargin = isReverseYAxis ? chartComputator.computeReverseRawYNoMargin(pointValue.getY()) : chartComputator.computeRawY(pointValue.getY());
            if (i == 0) {
                this.path.moveTo((float) computeRawX, (float) computeReverseRawYNoMargin);
            } else {
                float f = (float) computeRawX;
                this.path.lineTo(f, (float) d);
                this.path.lineTo(f, (float) computeReverseRawYNoMargin);
            }
            i++;
            d = computeReverseRawYNoMargin;
        }
        canvas.drawPath(this.path, this.linePaint);
        if (line.isFilled()) {
            drawArea(canvas, line);
        }
        this.path.reset();
    }

    private void drawSmoothPath(Canvas canvas, Line line) {
        double d;
        double d2;
        int i;
        double d3;
        double d4;
        double d5;
        double d6;
        prepareLinePaint(line);
        int size = line.getValues().size();
        double d7 = Double.NaN;
        double d8 = Double.NaN;
        double d9 = Double.NaN;
        double d10 = Double.NaN;
        double d11 = Double.NaN;
        int i2 = 0;
        double d12 = Double.NaN;
        while (i2 < size) {
            if (Double.isNaN(d7)) {
                PointValue pointValue = line.getValues().get(i2);
                double computeRawX = this.computator.computeRawX(pointValue.getX());
                d8 = this.computator.computeRawY(pointValue.getY());
                d7 = computeRawX;
            }
            if (!Double.isNaN(d12)) {
                d = d12;
                d2 = d10;
            } else if (i2 > 0) {
                PointValue pointValue2 = line.getValues().get(i2 - 1);
                d = this.computator.computeRawX(pointValue2.getX());
                d2 = this.computator.computeRawY(pointValue2.getY());
            } else {
                d = d7;
                d2 = d8;
            }
            if (Double.isNaN(d9)) {
                if (i2 > 1) {
                    PointValue pointValue3 = line.getValues().get(i2 - 2);
                    double computeRawX2 = this.computator.computeRawX(pointValue3.getX());
                    d11 = this.computator.computeRawY(pointValue3.getY());
                    d9 = computeRawX2;
                } else {
                    d11 = d2;
                    d9 = d;
                }
            }
            if (i2 < size - 1) {
                PointValue pointValue4 = line.getValues().get(i2 + 1);
                i = size;
                d3 = this.computator.computeRawX(pointValue4.getX());
                d4 = this.computator.computeRawY(pointValue4.getY());
            } else {
                i = size;
                d3 = d7;
                d4 = d8;
            }
            if (i2 == 0) {
                this.path.moveTo((float) d7, (float) d8);
                d5 = d4;
                d6 = d2;
            } else {
                d5 = d4;
                d6 = d2;
                this.path.cubicTo((float) (d + ((d7 - d9) * 0.1599999964237213d)), (float) (((d8 - d11) * 0.1599999964237213d) + d2), (float) (d7 - ((d3 - d) * 0.1599999964237213d)), (float) (d8 - ((d4 - d2) * 0.1599999964237213d)), (float) d7, (float) d8);
            }
            i2++;
            d12 = d7;
            d10 = d8;
            d9 = d;
            size = i;
            d7 = d3;
            d11 = d6;
            d8 = d5;
        }
        canvas.drawPath(this.path, this.linePaint);
        if (line.isFilled()) {
            drawArea(canvas, line);
        }
        this.path.reset();
    }

    private void prepareLinePaint(Line line) {
        this.linePaint.setStrokeWidth(ChartUtils.dp2px(this.density, line.getStrokeWidth()));
        this.linePaint.setColor(line.getColor());
        this.linePaint.setPathEffect(line.getPathEffect());
        this.linePaint.setShader(null);
    }

    private void drawPoints(Canvas canvas, Line line, int i, int i2) {
        HashMap hashMap;
        this.pointPaint.setColor(line.getPointColor());
        int dp2px = ChartUtils.dp2px(this.density, line.getPointRadius());
        double dp2px2 = ChartUtils.dp2px(this.density, line.getShadowRadius());
        boolean isReverseYAxis = line.isReverseYAxis();
        HashMap hashMap2 = new HashMap();
        int i3 = 0;
        boolean z = false;
        for (PointValue pointValue : line.getValues()) {
            double computeRawX = this.computator.computeRawX(pointValue.getX());
            ChartComputator chartComputator = this.computator;
            double computeReverseRawYNoMargin = isReverseYAxis ? chartComputator.computeReverseRawYNoMargin(pointValue.getY()) : chartComputator.computeRawY(pointValue.getY());
            if (this.computator.isWithinContentRect(computeRawX, computeReverseRawYNoMargin, this.checkPrecision)) {
                if (i2 == 0) {
                    if (pointValue.getPlumbPos() != -1.0d) {
                        if (!z) {
                            prepareLinePaint(line);
                            z = true;
                        }
                        drawSimplePath(canvas, pointValue, pointValue.getX(), pointValue.getPlumbPos());
                    }
                    drawPoint(canvas, line, pointValue, computeRawX, computeReverseRawYNoMargin, dp2px);
                    if (line.hasLabels()) {
                        drawLabel(canvas, line, pointValue, computeRawX, computeReverseRawYNoMargin, this.labelOffset + dp2px);
                    }
                    if (line.isBitmapLabels()) {
                        String finalLabelBitMapKey = pointValue.getFinalLabelBitMapKey();
                        Bitmap bitmap = (Bitmap) hashMap2.get(finalLabelBitMapKey);
                        if (bitmap == null && (bitmap = line.getBitmapCacheProvider().loadScaledBitmap(finalLabelBitMapKey)) != null) {
                            hashMap2.put(finalLabelBitMapKey, bitmap);
                        }
                        Bitmap bitmap2 = bitmap;
                        if (bitmap2 != null) {
                            hashMap = hashMap2;
                            drawLabelBitmap(canvas, line, pointValue, computeRawX, computeReverseRawYNoMargin, dp2px2, bitmap2);
                        }
                    }
                } else {
                    hashMap = hashMap2;
                    if (1 == i2) {
                        highlightPoint(canvas, line, pointValue, computeRawX, computeReverseRawYNoMargin, i, i3);
                    } else {
                        throw new IllegalStateException("Cannot process points in mode: " + i2);
                    }
                }
                i3++;
                hashMap2 = hashMap;
            }
            hashMap = hashMap2;
            i3++;
            hashMap2 = hashMap;
        }
    }

    private void drawPoint(Canvas canvas, Line line, PointValue pointValue, double d, double d2, double d3) {
        if (ValueShape.SQUARE.equals(line.getShape())) {
            canvas.drawRect((float) (d - d3), (float) (d2 - d3), (float) (d + d3), (float) (d2 + d3), this.pointPaint);
            return;
        }
        if (ValueShape.CIRCLE.equals(line.getShape())) {
            canvas.drawCircle((float) d, (float) d2, (float) d3, this.pointPaint);
            return;
        }
        if (ValueShape.DIAMOND.equals(line.getShape())) {
            canvas.save();
            canvas.rotate(45.0f, (float) d, (float) d2);
            canvas.drawRect((float) (d - d3), (float) (d2 - d3), (float) (d + d3), (float) (d2 + d3), this.pointPaint);
            canvas.restore();
            return;
        }
        throw new IllegalArgumentException("Invalid point shape: " + line.getShape());
    }

    private void highlightPoints(Canvas canvas) {
        int firstIndex = this.selectedValue.getFirstIndex();
        drawPoints(canvas, this.dataProvider.getLineChartData().getLines().get(firstIndex), firstIndex, 1);
    }

    private void highlightPoint(Canvas canvas, Line line, PointValue pointValue, double d, double d2, int i, int i2) {
        if (this.selectedValue.getFirstIndex() == i && this.selectedValue.getSecondIndex() == i2) {
            int dp2px = ChartUtils.dp2px(this.density, line.getPointRadius());
            this.pointPaint.setColor(line.getDarkenColor());
            drawPoint(canvas, line, pointValue, d, d2, this.touchToleranceMargin + dp2px);
            if (line.hasLabels() || line.hasLabelsOnlyForSelected()) {
                drawLabel(canvas, line, pointValue, d, d2, dp2px + this.labelOffset);
            }
        }
    }

    private void drawLabelBitmap(Canvas canvas, Line line, PointValue pointValue, double d, double d2, double d3, Bitmap bitmap) {
        Integer bitmapTint = pointValue.getBitmapTint();
        double width = bitmap.getWidth() / 2;
        double height = bitmap.getHeight() / 2;
        Integer bitmapLabelShadowColor = line.getBitmapLabelShadowColor();
        if (bitmapLabelShadowColor != null) {
            float f = (float) ((d3 + d) - width);
            float f2 = (float) ((d3 + d2) - height);
            canvas.drawBitmap(bitmap, f, f2, getTintedPaint(bitmapLabelShadowColor.intValue()));
            if (line.isFullShadow()) {
                double d4 = -d3;
                float f3 = (float) ((d4 + d) - width);
                float f4 = (float) ((d4 + d2) - height);
                canvas.drawBitmap(bitmap, f3, f4, getTintedPaint(bitmapLabelShadowColor.intValue()));
                canvas.drawBitmap(bitmap, f3, f2, getTintedPaint(bitmapLabelShadowColor.intValue()));
                canvas.drawBitmap(bitmap, f, f4, getTintedPaint(bitmapLabelShadowColor.intValue()));
            }
        }
        canvas.drawBitmap(bitmap, (float) (d - width), (float) (d2 - height), bitmapTint != null ? getTintedPaint(bitmapTint.intValue()) : this.labelPaint);
    }

    private void drawLabel(Canvas canvas, Line line, PointValue pointValue, double d, double d2, double d3) {
        double d4;
        double d5;
        double d6;
        double d7;
        Rect contentRectMinusAllMargins = this.computator.getContentRectMinusAllMargins();
        int formatChartValue = line.getFormatter().formatChartValue(this.labelBuffer, pointValue);
        if (formatChartValue == 0) {
            return;
        }
        Paint paint = this.labelPaint;
        char[] cArr = this.labelBuffer;
        double measureText = paint.measureText(cArr, cArr.length - formatChartValue, formatChartValue);
        int abs = Math.abs(this.fontMetrics.ascent);
        double d8 = measureText / 2.0d;
        int i = this.labelMargin;
        double d9 = (d - d8) - i;
        double d10 = d + d8 + i;
        if (pointValue.getY() >= this.baseValue) {
            d6 = d2 - d3;
            d4 = d10;
            d5 = (d6 - abs) - (this.labelMargin * 2);
        } else {
            d4 = d10;
            d5 = d2 + d3;
            d6 = (this.labelMargin * 2) + abs + d5;
        }
        if (d5 < contentRectMinusAllMargins.top) {
            d5 = d2 + d3;
            d6 = (this.labelMargin * 2) + abs + d5;
        }
        if (d6 > contentRectMinusAllMargins.bottom) {
            d6 = d2 - d3;
            d5 = (d6 - abs) - (this.labelMargin * 2);
        }
        if (d9 < contentRectMinusAllMargins.left) {
            d7 = (this.labelMargin * 2) + d + measureText;
            d9 = d;
        } else {
            d7 = d4;
        }
        if (d7 > contentRectMinusAllMargins.right) {
            d9 = (d - measureText) - (this.labelMargin * 2);
            d7 = d;
        }
        this.labelBackgroundRect.set((float) d9, (float) d5, (float) d7, (float) d6);
        char[] cArr2 = this.labelBuffer;
        drawLabelTextAndBackground(canvas, cArr2, cArr2.length - formatChartValue, formatChartValue, line.getDarkenColor());
    }

    private void drawArea(Canvas canvas, Line line) {
        double min;
        int size = line.getValues().size();
        if (size < 2) {
            return;
        }
        Rect maxContentRect = line.isBackgroundUnclipped() ? this.computator.getMaxContentRect() : this.computator.getContentRectMinusAllMargins();
        if (line.isFillFlipped()) {
            min = Math.min(maxContentRect.top, Math.min(this.computator.computeRawY(this.baseValue), maxContentRect.bottom));
        } else {
            min = Math.min(maxContentRect.bottom, Math.max(this.computator.computeRawY(this.baseValue), maxContentRect.top));
        }
        double max = Math.max(this.computator.computeRawX(line.getValues().get(0).getX()), maxContentRect.left);
        float f = (float) min;
        this.path.lineTo((float) Math.min(this.computator.computeRawX(line.getValues().get(size - 1).getX()), maxContentRect.right), f);
        this.path.lineTo((float) max, f);
        this.path.close();
        this.linePaint.setStyle(Paint.Style.FILL);
        this.linePaint.setAlpha(line.getAreaTransparency());
        if (line.isFillFlipped()) {
            this.linePaint.setShader(line.getGradientToTransparent() ? new LinearGradient(0.0f, (float) (canvas.getHeight() / line.getGradientDivider()), 0.0f, f, line.getColor(), line.getColor() & 16777215, Shader.TileMode.CLAMP) : null);
        } else {
            this.linePaint.setShader(line.getGradientToTransparent() ? new LinearGradient(0.0f, 0.0f, 0.0f, (float) (canvas.getHeight() / line.getGradientDivider()), line.getColor(), line.getColor() & 16777215, Shader.TileMode.MIRROR) : null);
        }
        canvas.drawPath(this.path, this.linePaint);
        this.linePaint.setStyle(Paint.Style.STROKE);
    }

    private boolean isInArea(double d, double d2, double d3, double d4, double d5) {
        return Math.pow(d3 - d, 2.0d) + Math.pow(d4 - d2, 2.0d) <= Math.pow(d5, 2.0d) * 2.0d;
    }
}