@Override
  public void drawData(Canvas c) {

    BubbleData bubbleData = mChart.getBubbleData();

    for (IBubbleDataSet set : bubbleData.getDataSets()) {

      if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set);
    }
  }
  @Override
  public void drawValues(Canvas c) {

    BubbleData bubbleData = mChart.getBubbleData();

    if (bubbleData == null) return;

    // if values are drawn
    if (bubbleData.getYValCount()
        < (int) (Math.ceil((float) (mChart.getMaxVisibleCount()) * mViewPortHandler.getScaleX()))) {

      final List<IBubbleDataSet> dataSets = bubbleData.getDataSets();

      float lineHeight = Utils.calcTextHeight(mValuePaint, "1");

      for (int i = 0; i < dataSets.size(); i++) {

        IBubbleDataSet dataSet = dataSets.get(i);

        if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue;

        // apply the text-styling defined by the DataSet
        applyValueTextStyle(dataSet);

        final float phaseX = mAnimator.getPhaseX();
        final float phaseY = mAnimator.getPhaseY();

        BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX);
        BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX);

        int minx = dataSet.getEntryIndex(entryFrom);
        int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount());

        final float[] positions =
            mChart
                .getTransformer(dataSet.getAxisDependency())
                .generateTransformedValuesBubble(dataSet, phaseX, phaseY, minx, maxx);

        for (int j = 0; j < positions.length; j += 2) {

          final float alpha = phaseX == 1 ? phaseY : phaseX;
          int valueTextColor = dataSet.getValueTextColor(j / 2);
          valueTextColor =
              Color.argb(
                  Math.round(255.f * alpha),
                  Color.red(valueTextColor),
                  Color.green(valueTextColor),
                  Color.blue(valueTextColor));

          float x = positions[j];
          float y = positions[j + 1];

          if (!mViewPortHandler.isInBoundsRight(x)) break;

          if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) continue;

          BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + minx);

          drawValue(
              c,
              dataSet.getValueFormatter(),
              entry.getSize(),
              entry,
              i,
              x,
              y + (0.5f * lineHeight),
              valueTextColor);
        }
      }
    }
  }