content: 
  package com.github.mikephil.charting.utils;
  
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.graphics.Paint;
  import android.graphics.Typeface;
  
  import java.util.ArrayList;
  
  /**
   * Class representing the legend of the chart. The legend will contain one entry
   * per color and DataSet. Multiple colors in one DataSet are grouped together.
   * The legend object is NOT available before setting data to the chart.
   * 
   * @author Philipp Jahoda
   */
  public class Legend {
  
      public enum LegendPosition {
          RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER, PIECHART_CENTER, NONE
      }
  
      public enum LegendForm {
          SQUARE, CIRCLE, LINE
      }
  
      /** offsets for the legend */
      private float mLegendOffsetBottom = 12f, mLegendOffsetRight = 12f, mLegendOffsetLeft = 12f,
              mLegendOffsetTop = 12f;
  
      /** the legend colors */
      private int[] mColors;
  
      /** the legend labels */
      private String[] mLegendLabels;
  
      /** the position relative to the chart the legend is drawn on */
      private LegendPosition mPosition = LegendPosition.BELOW_CHART_LEFT;
  
      /** the shape/form the legend colors are drawn in */
      private LegendForm mShape = LegendForm.SQUARE;
  
      /** the typeface used for the legend labels */
      private Typeface mTypeface = null;
  
      /** the text size of the legend labels */
      private float mTextSize = 9f;
  
      /** the text color to use */
      private int mTextColor = Color.BLACK;
  
      /** the size of the legend forms/shapes */
      private float mFormSize = 8f;
  
      /**
       * the space between the legend entries on a horizontal axis, default 6f
       */
      private float mXEntrySpace = 6f;
  
      /**
       * the space between the legend entries on a vertical axis, default 5f
       */
      private float mYEntrySpace = 5f;
  
      /**
       * the space between the legend entries on a vertical axis, default 2f
       * private float mYEntrySpace = 2f; /** the space between the form and the
       * actual label/text
       */
      private float mFormToTextSpace = 5f;
  
      /** the space that should be left between stacked forms */
      private float mStackSpace = 3f;
  
      /** default constructor */
      public Legend() {
  
          mFormSize = Utils.convertDpToPixel(8f);
          mXEntrySpace = Utils.convertDpToPixel(6f);
          mYEntrySpace = Utils.convertDpToPixel(5f);
          mFormToTextSpace = Utils.convertDpToPixel(5f);
          mTextSize = Utils.convertDpToPixel(9f);
          mStackSpace = Utils.convertDpToPixel(3f);
      }
  
      /**
       * Constructor. Provide colors and labels for the legend.
       * 
       * @param colors
       * @param labels
       */
      public Legend(int[] colors, String[] labels) {
          this();
  
          if (colors == null || labels == null) {
              throw new IllegalArgumentException("colors array or labels array is NULL");
          }
  
          if (colors.length != labels.length) {
              throw new IllegalArgumentException(
                      "colors array and labels array need to be of same size");
          }
  
          this.mColors = colors;
          this.mLegendLabels = labels;
      }
  
      /**
       * Constructor. Provide colors and labels for the legend.
       * 
       * @param colors
       * @param labels
       */
      public Legend(ArrayList<Integer> colors, ArrayList<String> labels) {
          this();
  
          if (colors == null || labels == null) {
              throw new IllegalArgumentException("colors array or labels array is NULL");
          }
  
          if (colors.size() != labels.size()) {
              throw new IllegalArgumentException(
                      "colors array and labels array need to be of same size");
          }
  
          this.mColors = Utils.convertIntegers(colors);
          this.mLegendLabels = Utils.convertStrings(labels);
      }
  
      /**
       * returns the maximum length in pixels over all legend labels + their forms
       * 
       * @param p the paint object used for rendering the text
       * @return
       */
      public int getMaximumEntryLength(Paint p) {
  
          int max = 0;
  
          for (int i = 0; i < mLegendLabels.length; i++) {
  
              if (mLegendLabels[i] != null) {
  
                  int length = Utils.calcTextWidth(p, mLegendLabels[i]);
  
                  if (length > max)
                      max = length;
              }
          }
  
          return max + (int) mFormSize;
      }
  
      /**
       * returns all the colors the legend uses
       * 
       * @return
       */
      public int[] getColors() {
          return mColors;
      }
  
      /**
       * returns all the labels the legend uses
       * 
       * @return
       */
      public String[] getLegendLabels() {
          return mLegendLabels;
      }
  
      /**
       * Sets a custom array of labels for the legend. Make sure the labels array
       * has the same length as the colors array.
       * 
       * @param labels
       */
      public void setLegendLabels(String[] labels) {
  
          if (mColors.length != labels.length) {
              throw new IllegalArgumentException(
                      "colors array and labels array need to be of same size");
          }
  
          this.mLegendLabels = labels;
      }
  
      /**
       * returns the position of the legend relative to the chart
       * 
       * @return
       */
      public LegendPosition getPosition() {
          return mPosition;
      }
  
      /**
       * sets the position of the legend relative to the whole chart
       * 
       * @param pos
       */
      public void setPosition(LegendPosition pos) {
          mPosition = pos;
      }
  
      /**
       * returns the current form/shape that is set for the legend
       * 
       * @return
       */
      public LegendForm getForm() {
          return mShape;
      }
  
      /**
       * sets the form/shape of the legend forms
       * 
       * @param shape
       */
      public void setForm(LegendForm shape) {
          mShape = shape;
      }
  
      /**
       * returns the typeface used for the legend labels, returns null if none is
       * set
       * 
       * @return
       */
      public Typeface getTypeface() {
          return mTypeface;
      }
  
      /**
       * sets a specific typeface for the legend labels
       * 
       * @param tf
       */
      public void setTypeface(Typeface tf) {
          mTypeface = tf;
      }
  
      /**
       * sets the size in pixels of the legend forms, this is internally converted
       * in dp, default 8f
       * 
       * @param size
       */
      public void setFormSize(float size) {
          mFormSize = Utils.convertDpToPixel(size);
      }
  
      /**
       * returns the size in dp of the legend forms
       * 
       * @return
       */
      public float getFormSize() {
          return mFormSize;
      }
  
      /**
       * returns the space between the legend entries on a horizontal axis in
       * pixels
       * 
       * @return
       */
      public float getXEntrySpace() {
          return mXEntrySpace;
      }
  
      /**
       * sets the space between the legend entries on a horizontal axis in pixels,
       * converts to dp internally
       * 
       * @param space
       */
      public void setXEntrySpace(float space) {
          mXEntrySpace = Utils.convertDpToPixel(space);
      }
  
      /**
       * returns the space between the legend entries on a vertical axis in pixels
       * 
       * @return
       */
      public float getYEntrySpace() {
          return mYEntrySpace;
      }
  
      /**
       * sets the space between the legend entries on a vertical axis in pixels,
       * converts to dp internally
       * 
       * @param space
       */
      public void setYEntrySpace(float space) {
          mYEntrySpace = Utils.convertDpToPixel(space);
      }
  
      /**
       * returns the space between the form and the actual label/text
       * 
       * @return
       */
      public float getFormToTextSpace() {
          return mFormToTextSpace;
      }
  
      /**
       * sets the space between the form and the actual label/text, converts to dp
       * internally
       * 
       * @param mFormToTextSpace
       */
      public void setFormToTextSpace(float space) {
          this.mFormToTextSpace = Utils.convertDpToPixel(space);
      }
  
      /**
       * draws the form at the given position with the color at the given index
       * 
       * @param c canvas to draw with
       * @param x
       * @param y
       * @param p paint to use for drawing
       * @param index the index of the color to use (in the colors array)
       */
      public void drawForm(Canvas c, float x, float y, Paint p, int index) {
  
          if (mColors[index] == -2)
              return;
  
          p.setColor(mColors[index]);
  
          float half = mFormSize / 2f;
  
          switch (getForm()) {
              case CIRCLE:
                  c.drawCircle(x + half, y + half, half, p);
                  break;
              case SQUARE:
                  c.drawRect(x, y, x + mFormSize, y + mFormSize, p);
                  break;
              case LINE:
                  c.drawLine(x, y + half, x + mFormSize, y + half, p);
                  break;
          }
      }
  
      /**
       * draws the label at the given index in the labels array at the given
       * position
       * 
       * @param c canvas to draw with
       * @param x
       * @param y
       * @param p paint to use for drawing
       * @param index index in the labels-array
       */
      public void drawLabel(Canvas c, float x, float y, Paint p, int index) {
  
          c.drawText(mLegendLabels[index], x, y, p);
      }
  
      /**
       * applies the state from the legend in the parameter to this legend (except
       * colors, labels and offsets)
       * 
       * @param l
       */
      public void apply(Legend l) {
  
          mPosition = l.mPosition;
          mShape = l.mShape;
          mTypeface = l.mTypeface;
          mFormSize = l.mFormSize;
          mXEntrySpace = l.mXEntrySpace;
          mYEntrySpace = l.mYEntrySpace;
          mFormToTextSpace = l.mFormToTextSpace;
          mTextSize = l.mTextSize;
          mStackSpace = l.mStackSpace;
          mTextColor = l.mTextColor;
  
          // apply offsets
          mLegendOffsetBottom = l.mLegendOffsetBottom;
          mLegendOffsetLeft = l.mLegendOffsetLeft;
          mLegendOffsetRight = l.mLegendOffsetRight;
          mLegendOffsetTop = l.mLegendOffsetTop;
      }
  
      /**
       * returns the bottom offset
       * 
       * @return
       */
      public float getOffsetBottom() {
          return mLegendOffsetBottom;
      }
  
      /**
       * returns the right offset
       * 
       * @return
       */
      public float getOffsetRight() {
          return mLegendOffsetRight;
      }
  
      /**
       * sets the bottom offset
       * 
       * @param off
       */
      public void setOffsetBottom(float off) {
          mLegendOffsetBottom = off;
      }
  
      /**
       * sets the right offset
       * 
       * @param off
       */
      public void setOffsetRight(float off) {
          mLegendOffsetRight = off;
      }
  
      /**
       * returns the bottom offset
       * 
       * @return
       */
      public float getOffsetTop() {
          return mLegendOffsetTop;
      }
  
      /**
       * returns the left offset
       * 
       * @return
       */
      public float getOffsetLeft() {
          return mLegendOffsetLeft;
      }
  
      /**
       * sets the bottom offset
       * 
       * @param off
       */
      public void setOffsetTop(float off) {
          mLegendOffsetTop = off;
      }
  
      /**
       * sets the left offset
       * 
       * @param off
       */
      public void setOffsetLeft(float off) {
          mLegendOffsetLeft = off;
      }
  
      /**
       * sets the text size of the legend labels, default 9f
       * 
       * @param size
       */
      public void setTextSize(float size) {
          mTextSize = Utils.convertDpToPixel(size);
      }
  
      /**
       * returns the text size of the legend labels
       * 
       * @return
       */
      public float getTextSize() {
          return mTextSize;
      }
  
      /**
       * returns the space that is left out between stacked forms (with no label)
       * 
       * @return
       */
      public float getStackSpace() {
          return mStackSpace;
      }
  
      /**
       * sets the space that is left out between stacked forms (with no label)
       * 
       * @param space
       */
      public void setStackSpace(float space) {
          mStackSpace = space;
      }
  
      /**
       * calculates the full width the fully drawn legend will use in pixels
       * 
       * @return
       */
      public float getFullWidth(Paint labelpaint) {
  
          float width = 0f;
  
          for (int i = 0; i < mLegendLabels.length; i++) {
  
              // grouped forms have null labels
              if (mLegendLabels[i] != null) {
  
                  // make a step to the left
                  if (mColors[i] != -2)
                      width += mFormSize + mFormToTextSpace;
  
                  width += Utils.calcTextWidth(labelpaint, mLegendLabels[i])
                          + mXEntrySpace;
              } else {
                  width += mFormSize + mStackSpace;
              }
          }
  
          return width;
      }
  
      /**
       * Calculates the full height of the drawn legend.
       * 
       * @param mLegendLabelPaint
       * @return
       */
      public float getFullHeight(Paint labelpaint) {
  
          float height = 0f;
  
          for (int i = 0; i < mLegendLabels.length; i++) {
  
              // grouped forms have null labels
              if (mLegendLabels[i] != null) {
  
                  height += Utils.calcTextHeight(labelpaint, mLegendLabels[i])
                          + mYEntrySpace;
              }
          }
  
          return height;
      }
  
      /**
       * Sets the text color to use for the legend labels. Make sure to use
       * getResources().getColor(...) when using a color from the resources.
       * 
       * @param color
       */
      public void setTextColor(int color) {
          mTextColor = color;
      }
  
      /**
       * Returns the text color that is set for the legend labels.
       * 
       * @return
       */
      public int getTextColor() {
          return mTextColor;
      }
  }
  