/**
   * Measure the text, stopping early if the measured width exceeds maxWidth. Return the number of
   * chars that were measured, and if measuredWidth is not null, return in it the actual width
   * measured.
   *
   * @param text The text to measure
   * @param start The offset into text to begin measuring at
   * @param end The end of the text slice to measure.
   * @param measureForwards If true, measure forwards, starting at start. Otherwise, measure
   *     backwards, starting with end.
   * @param maxWidth The maximum width to accumulate.
   * @param measuredWidth Optional. If not null, returns the actual width measured.
   * @return The number of chars that were measured. Will always be <= abs(end - start).
   */
  public int breakText(
      CharSequence text,
      int start,
      int end,
      boolean measureForwards,
      float maxWidth,
      float[] measuredWidth) {
    if (start == 0 && text instanceof String && end == text.length()) {
      return breakText((String) text, measureForwards, maxWidth, measuredWidth);
    }

    char[] buf = TemporaryBuffer.obtain(end - start);
    int result;

    TextUtils.getChars(text, start, end, buf, 0);

    if (measureForwards) {
      result = breakText(buf, 0, end - start, maxWidth, measuredWidth);
    } else {
      result = breakText(buf, 0, -(end - start), maxWidth, measuredWidth);
    }

    TemporaryBuffer.recycle(buf);
    return result;
  }
  /**
   * Return the width of the text.
   *
   * @param text The text to measure
   * @param start The index of the first character to start measuring
   * @param end 1 beyond the index of the last character to measure
   * @return The width of the text
   */
  public float measureText(CharSequence text, int start, int end) {
    if (text instanceof String) {
      return measureText((String) text, start, end);
    }
    if (text instanceof SpannedString || text instanceof SpannableString) {
      return measureText(text.toString(), start, end);
    }
    if (text instanceof GraphicsOperations) {
      return ((GraphicsOperations) text).measureText(start, end, this);
    }

    char[] buf = TemporaryBuffer.obtain(end - start);
    TextUtils.getChars(text, start, end, buf, 0);
    float result = measureText(buf, 0, end - start);
    TemporaryBuffer.recycle(buf);
    return result;
  }
  /**
   * Return the advance widths for the characters in the string.
   *
   * @param text The text to measure
   * @param start The index of the first char to to measure
   * @param end The end of the text slice to measure
   * @param widths array to receive the advance widths of the characters. Must be at least a large
   *     as (end - start).
   * @return the actual number of widths returned.
   */
  public int getTextWidths(CharSequence text, int start, int end, float[] widths) {
    if (text instanceof String) {
      return getTextWidths((String) text, start, end, widths);
    }
    if (text instanceof SpannedString || text instanceof SpannableString) {
      return getTextWidths(text.toString(), start, end, widths);
    }
    if (text instanceof GraphicsOperations) {
      return ((GraphicsOperations) text).getTextWidths(start, end, widths, this);
    }

    char[] buf = TemporaryBuffer.obtain(end - start);
    TextUtils.getChars(text, start, end, buf, 0);
    int result = getTextWidths(buf, 0, end - start, widths);
    TemporaryBuffer.recycle(buf);
    return result;
  }