class LineAndPointRenderer extends XYSeriesRenderer<XYSeries, FormatterType> {

    protected void renderPath(Canvas canvas, RectF plotArea, Path path, PointF firstPoint, PointF lastPoint, LineAndPointFormatter formatter) {
        Path outlinePath = new Path(path);

        // determine how to close the path for filling purposes:
        // We always need to calculate this path because it is also used for
        // masking off for region highlighting.
        switch (formatter.getFillDirection()) {
            case BOTTOM:
                path.lineTo(lastPoint.x, plotArea.bottom);
                path.lineTo(firstPoint.x, plotArea.bottom);
                path.close();
                break;
            case TOP:
                path.lineTo(lastPoint.x, plotArea.top);
                path.lineTo(firstPoint.x, plotArea.top);
                path.close();
                break;
            case RANGE_ORIGIN:
                float originPix = (float) getPlot().getBounds().getxRegion()
                        .transform(getPlot().getRangeOrigin()
                                .doubleValue(), plotArea.top, plotArea.bottom, true);
                path.lineTo(lastPoint.x, originPix);
                path.lineTo(firstPoint.x, originPix);
                path.close();
                break;
            default:
                throw new UnsupportedOperationException(
                        "Fill direction not yet implemented: " + formatter.getFillDirection());
        }

        if (formatter.getFillPaint() != null) {
            canvas.drawPath(path, formatter.getFillPaint());
        }

        final RectRegion bounds = getPlot().getBounds();
        final RectRegion plotRegion = new RectRegion(plotArea);

        // draw each region:
        for (RectRegion thisRegion : bounds.intersects(formatter.getRegions().elements())) {
            XYRegionFormatter regionFormatter = formatter.getRegionFormatter(thisRegion);
            RectRegion thisRegionTransformed = bounds
                    .transform(thisRegion, plotRegion, false, true);
            thisRegionTransformed.intersect(plotRegion);
            if(thisRegion.isFullyDefined()) {
                RectF thisRegionRectF = thisRegionTransformed.asRectF();
                if (thisRegionRectF != null) {
                    try {
                        canvas.save();
                        canvas.clipPath(path);
                        canvas.drawRect(thisRegionRectF, regionFormatter.getPaint());
                    } finally {
                        canvas.restore();
                    }
                }
            }
        }

        // finally we draw the outline path on top of everything else:
        if(formatter.hasLinePaint()) {
            canvas.drawPath(outlinePath, formatter.getLinePaint());
        }

        path.rewind();
    }

    public  LineAndPointRenderer(XYPlot plot);

}