public LegendRenderer(ViewPortHandler viewPortHandler, Legend legend) {
    super(viewPortHandler);

    this.mLegend = legend;

    mLegendLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mLegendLabelPaint.setTextSize(Utils.convertDpToPixel(9f));
    mLegendLabelPaint.setTextAlign(Align.LEFT);

    mLegendFormPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mLegendFormPaint.setStyle(Paint.Style.FILL);
    mLegendFormPaint.setStrokeWidth(3f);

    legend.setEnabled(false);
  }
  public void renderLegend(Canvas c) {

    if (!mLegend.isEnabled()) return;

    Typeface tf = mLegend.getTypeface();

    if (tf != null) mLegendLabelPaint.setTypeface(tf);

    mLegendLabelPaint.setTextSize(mLegend.getTextSize());
    mLegendLabelPaint.setColor(mLegend.getTextColor());

    float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint);
    float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint) + mLegend.getYEntrySpace();
    float formYOffset = labelLineHeight - Utils.calcTextHeight(mLegendLabelPaint, "ABC") / 2.f;

    String[] labels = mLegend.getLabels();
    int[] colors = mLegend.getColors();

    float formToTextSpace = mLegend.getFormToTextSpace();
    float xEntrySpace = mLegend.getXEntrySpace();
    Legend.LegendDirection direction = mLegend.getDirection();
    float formSize = mLegend.getFormSize();

    // space between the entries
    float stackSpace = mLegend.getStackSpace();

    float posX, posY;

    float yoffset = mLegend.getYOffset();
    float xoffset = mLegend.getXOffset();

    Legend.LegendPosition legendPosition = mLegend.getPosition();

    switch (legendPosition) {
      case BELOW_CHART_LEFT:
      case BELOW_CHART_RIGHT:
      case BELOW_CHART_CENTER:
        {
          float contentWidth = mViewPortHandler.contentWidth();

          float originPosX;

          if (legendPosition == Legend.LegendPosition.BELOW_CHART_LEFT) {
            originPosX = mViewPortHandler.contentLeft() + xoffset;

            if (direction == Legend.LegendDirection.RIGHT_TO_LEFT)
              originPosX += mLegend.mNeededWidth;
          } else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT) {
            originPosX = mViewPortHandler.contentRight() - xoffset;

            if (direction == Legend.LegendDirection.LEFT_TO_RIGHT)
              originPosX -= mLegend.mNeededWidth;
          } else // if (legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER)
          originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f;

          FSize[] calculatedLineSizes = mLegend.getCalculatedLineSizes();
          FSize[] calculatedLabelSizes = mLegend.getCalculatedLabelSizes();
          Boolean[] calculatedLabelBreakPoints = mLegend.getCalculatedLabelBreakPoints();

          posX = originPosX;
          posY = mViewPortHandler.getChartHeight() - yoffset - mLegend.mNeededHeight;

          int lineIndex = 0;

          for (int i = 0, count = labels.length; i < count; i++) {
            if (calculatedLabelBreakPoints[i]) {
              posX = originPosX;
              posY += labelLineHeight + labelLineSpacing;
            }

            if (posX == originPosX && legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER) {
              posX +=
                  (direction == Legend.LegendDirection.RIGHT_TO_LEFT
                          ? calculatedLineSizes[lineIndex].width
                          : -calculatedLineSizes[lineIndex].width)
                      / 2.f;
              lineIndex++;
            }

            boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP;
            boolean isStacked = labels[i] == null; // grouped forms have null labels

            if (drawingForm) {
              if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) posX -= formSize;

              drawForm(c, posX, posY + formYOffset, i, mLegend);

              if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) posX += formSize;
            }

            if (!isStacked) {
              if (drawingForm)
                posX +=
                    direction == Legend.LegendDirection.RIGHT_TO_LEFT
                        ? -formToTextSpace
                        : formToTextSpace;

              if (direction == Legend.LegendDirection.RIGHT_TO_LEFT)
                posX -= calculatedLabelSizes[i].width;

              drawLabel(c, posX, posY + labelLineHeight, labels[i]);

              if (direction == Legend.LegendDirection.LEFT_TO_RIGHT)
                posX += calculatedLabelSizes[i].width;

              posX +=
                  direction == Legend.LegendDirection.RIGHT_TO_LEFT ? -xEntrySpace : xEntrySpace;
            } else
              posX += direction == Legend.LegendDirection.RIGHT_TO_LEFT ? -stackSpace : stackSpace;
          }
        }
        break;

      case PIECHART_CENTER:
      case RIGHT_OF_CHART:
      case RIGHT_OF_CHART_CENTER:
      case RIGHT_OF_CHART_INSIDE:
      case LEFT_OF_CHART:
      case LEFT_OF_CHART_CENTER:
      case LEFT_OF_CHART_INSIDE:
        {
          // contains the stacked legend size in pixels
          float stack = 0f;
          boolean wasStacked = false;

          if (legendPosition == Legend.LegendPosition.PIECHART_CENTER) {
            posX =
                mViewPortHandler.getChartWidth() / 2f
                    + (direction == Legend.LegendDirection.LEFT_TO_RIGHT
                        ? -mLegend.mTextWidthMax / 2f
                        : mLegend.mTextWidthMax / 2f);
            posY =
                mViewPortHandler.getChartHeight() / 2f
                    - mLegend.mNeededHeight / 2f
                    + mLegend.getYOffset();
          } else {
            boolean isRightAligned =
                legendPosition == Legend.LegendPosition.RIGHT_OF_CHART
                    || legendPosition == Legend.LegendPosition.RIGHT_OF_CHART_CENTER
                    || legendPosition == Legend.LegendPosition.RIGHT_OF_CHART_INSIDE;

            if (isRightAligned) {
              posX = mViewPortHandler.getChartWidth() - xoffset;
              if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) posX -= mLegend.mTextWidthMax;
            } else {
              posX = xoffset;
              if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) posX += mLegend.mTextWidthMax;
            }

            if (legendPosition == Legend.LegendPosition.RIGHT_OF_CHART
                || legendPosition == Legend.LegendPosition.LEFT_OF_CHART) {
              posY = mViewPortHandler.contentTop() + yoffset;
            } else if (legendPosition == Legend.LegendPosition.RIGHT_OF_CHART_CENTER
                || legendPosition == Legend.LegendPosition.LEFT_OF_CHART_CENTER) {
              posY = mViewPortHandler.getChartHeight() / 2f - mLegend.mNeededHeight / 2f;
            } else /*
                    * if (legendPosition ==
                    * Legend.LegendPosition.RIGHT_OF_CHART_INSIDE ||
                    * legendPosition ==
                    * Legend.LegendPosition.LEFT_OF_CHART_INSIDE)
                    */ {
              posY = mViewPortHandler.contentTop() + yoffset;
            }
          }

          for (int i = 0; i < labels.length; i++) {

            Boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP;
            float x = posX;

            if (drawingForm) {
              if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) x += stack;
              else x -= formSize - stack;

              drawForm(c, x, posY + formYOffset, i, mLegend);

              if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) x += formSize;
            }

            if (labels[i] != null) {

              if (drawingForm && !wasStacked)
                x +=
                    direction == Legend.LegendDirection.LEFT_TO_RIGHT
                        ? formToTextSpace
                        : -formToTextSpace;
              else if (wasStacked) x = posX;

              if (direction == Legend.LegendDirection.RIGHT_TO_LEFT)
                x -= Utils.calcTextWidth(mLegendLabelPaint, labels[i]);

              if (!wasStacked) {
                drawLabel(c, x, posY + labelLineHeight, labels[i]);
              } else {
                posY += labelLineHeight + labelLineSpacing;
                drawLabel(c, x, posY + labelLineHeight, labels[i]);
              }

              // make a step down
              posY += labelLineHeight + labelLineSpacing;
              stack = 0f;
            } else {
              stack += formSize + stackSpace;
              wasStacked = true;
            }
          }
        }
        break;
    }
  }