class LineAndPointRenderer extends XYSeriesRenderer<XYSeries, FormatterType> {

    protected void drawSeries(Canvas canvas, RectF plotArea, XYSeries series, LineAndPointFormatter formatter) {
        PointF thisPoint;
        PointF lastPoint = null;
        PointF firstPoint = null;
        path.reset();
        final List<PointF> points = getPointsCache(series);

        int iStart = 0;
        int iEnd = series.size();
        if(SeriesUtils.getXYOrder(series) == OrderedXYSeries.XOrder.ASCENDING) {
            final Region iBounds = SeriesUtils.iBounds(series, getPlot().getBounds());
            iStart = iBounds.getMin().intValue();
            if(iStart > 0) {
                iStart--;
            }
            iEnd = iBounds.getMax().intValue() + 1;
            if(iEnd < series.size() - 1) {
                iEnd++;
            }
        }
        for (int i = iStart; i < iEnd; i++) {
            final Number y = series.getY(i);
            final Number x = series.getX(i);
            PointF iPoint = points.get(i);

            if (y != null && x != null) {
                if(iPoint == null) {
                    iPoint = new PointF();
                    points.set(i, iPoint);
                }
                thisPoint = iPoint;
                getPlot().getBounds().transformScreen(thisPoint, x, y, plotArea);
            } else {
                thisPoint = null;
                iPoint = null;
                points.set(i, iPoint);
            }

            // don't need to do any of this if the line isnt going to be drawn:
            if(formatter.hasLinePaint() && formatter.getInterpolationParams() == null) {
                if (thisPoint != null) {

                    // record the first point of the new Path
                    if (firstPoint == null) {
                        path.reset();
                        firstPoint = thisPoint;

                        // create our first point at the bottom/x position so filling will look good:
                        path.moveTo(firstPoint.x, firstPoint.y);
                    }

                    if (lastPoint != null) {
                        appendToPath(path, thisPoint, lastPoint);
                    }

                    lastPoint = thisPoint;
                } else {
                    if (lastPoint != null) {
                        renderPath(canvas, plotArea, path, firstPoint, lastPoint, formatter);
                    }
                    firstPoint = null;
                    lastPoint = null;
                }
            }
        }

        if(formatter.hasLinePaint()) {
            if(formatter.getInterpolationParams() != null) {
                List<XYCoords> interpolatedPoints = getInterpolator(
                        formatter.getInterpolationParams()).interpolate(series,
                        formatter.getInterpolationParams());
                firstPoint = convertPoint(interpolatedPoints.get(ZERO), plotArea);
                lastPoint = convertPoint(interpolatedPoints.get(interpolatedPoints.size()-ONE), plotArea);
                path.reset();
                path.moveTo(firstPoint.x, firstPoint.y);
                for(int i = 1; i < interpolatedPoints.size(); i++) {
                    thisPoint = convertPoint(interpolatedPoints.get(i), plotArea);
                    path.lineTo(thisPoint.x, thisPoint.y);
                }
            }

            if(firstPoint != null) {
                renderPath(canvas, plotArea, path, firstPoint, lastPoint, formatter);
            }
        }
        renderPoints(canvas, plotArea, series, iStart, iEnd, points, formatter);
    }

    public  LineAndPointRenderer(XYPlot plot);

}