public int computeMaximumTextSize(final long contentX2) {
    final int length = getLength();
    final long x = getX();
    if (contentX2 >= (x + getWidth())) {
      return length;
    }

    final GlyphList gs = getGlyphs();
    long runningPos = x;
    final int offset = getOffset();
    final int maxPos = offset + length;

    for (int i = offset; i < maxPos; i++) {
      final Glyph g = gs.getGlyph(i);
      runningPos += RenderableText.convert(g.getWidth());
      if (i != offset) {
        runningPos += g.getSpacing().getMinimum();
      }
      if (runningPos > contentX2) {
        return Math.max(0, i - offset);
      }
    }
    return length;
  }
  protected void initialize(
      final GlyphList glyphs,
      final int offset,
      final int length,
      final ExtendedBaselineInfo baselineInfo,
      final int script,
      final boolean forceLinebreak) {
    if (glyphs == null) {
      throw new NullPointerException();
    }
    if (forceLinebreak == false && length == 0) {
      throw new IllegalArgumentException("Do not create zero-length renderable text!");
    }
    if (glyphs.getSize() < (offset + length)) {
      throw new IllegalArgumentException();
    }

    this.baselineInfo = baselineInfo;
    this.ltr = true; // this depends on the script value
    this.script = script;

    this.glyphs = glyphs;
    this.offset = offset;
    this.length = length;
    this.forceLinebreak = forceLinebreak;

    normalTextSpacing = true;
    long wordMinChunkWidth = 0;

    //    long heightAbove = 0;
    //    long heightBelow = 0;
    long minimumChunkWidth = 0;

    long realCharTotal = 0;
    long spacerMin = 0;
    long spacerMax = 0;
    long spacerOpt = 0;

    final int lastPos = Math.min(glyphs.getSize(), offset + length);
    for (int i = offset; i < lastPos; i++) {
      final Glyph glyph = glyphs.getGlyph(i);
      //      heightAbove = Math.max(glyph.getBaseLine(), heightAbove);
      //      heightBelow = Math.max(glyph.getHeight() - glyph.getBaseLine(), heightBelow);
      final int kerning = glyph.getKerning();
      final int width = glyph.getWidth();
      final long realCharSpace = convert(width - kerning);
      realCharTotal += realCharSpace;
      wordMinChunkWidth += realCharSpace;
      if (i != (lastPos - 1)) {
        final Spacing spacing = glyph.getSpacing();
        spacerMax += spacing.getMaximum();
        spacerMin += spacing.getMinimum();
        spacerOpt += spacing.getOptimum();
        if (normalTextSpacing == true && Spacing.EMPTY_SPACING.equals(spacing) == false) {
          normalTextSpacing = false;
        }

        wordMinChunkWidth += spacing.getMinimum();
      }

      if (glyph.getBreakWeight() > BreakOpportunityProducer.BREAK_CHAR) {
        minimumChunkWidth = Math.max(minimumChunkWidth, wordMinChunkWidth);
        wordMinChunkWidth = 0;

        // Paranoid sanity checks: The word- and linebreaks should have been
        // replaced by other definitions in the text factory.
        if (glyph.getBreakWeight() == BreakOpportunityProducer.BREAK_LINE) {
          throw new IllegalStateException(
              "A renderable text cannot and must " + "not contain linebreaks.");
        }
      }
    }

    final long wordMinWidth = spacerMin + realCharTotal;
    final long wordPrefWidth = spacerOpt + realCharTotal;
    final long wordMaxWidth = spacerMax + realCharTotal;

    minimumChunkWidth = Math.max(minimumChunkWidth, wordMinChunkWidth);
    minimumWidth = wordMinWidth;
    preferredWidth = wordPrefWidth;

    setMaximumBoxWidth(wordMaxWidth);
    setMinimumChunkWidth(minimumChunkWidth);
  }