private TextLine makeTextLineOnRange(int startPos, int limitPos) {

    int[] charsLtoV = null;
    byte[] charLevels = null;

    if (fBidi != null) {
      Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos);
      charLevels = BidiUtils.getLevels(lineBidi);
      int[] charsVtoL = BidiUtils.createVisualToLogicalMap(charLevels);
      charsLtoV = BidiUtils.createInverseMap(charsVtoL);
    }

    TextLineComponent[] components = makeComponentsOnRange(startPos, limitPos);

    return new TextLine(
        fFrc,
        components,
        fBaselineOffsets,
        fChars,
        startPos,
        limitPos,
        charsLtoV,
        charLevels,
        fIsDirectionLTR);
  }
  /** Generate components for the paragraph. fChars, fBidi should have been initialized already. */
  private void generateComponents(int startingAt, int endingAt) {

    if (collectStats) {
      formattedChars += (endingAt - startingAt);
    }
    int layoutFlags = 0; // no extra info yet, bidi determines run and line direction
    TextLabelFactory factory = new TextLabelFactory(fFrc, fChars, fBidi, layoutFlags);

    int[] charsLtoV = null;

    if (fBidi != null) {
      fLevels = BidiUtils.getLevels(fBidi);
      int[] charsVtoL = BidiUtils.createVisualToLogicalMap(fLevels);
      charsLtoV = BidiUtils.createInverseMap(charsVtoL);
      fIsDirectionLTR = fBidi.baseIsLeftToRight();
    } else {
      fLevels = null;
      fIsDirectionLTR = true;
    }

    try {
      fComponents =
          TextLine.getComponents(
              fParagraph, fChars, startingAt, endingAt, charsLtoV, fLevels, factory);
    } catch (IllegalArgumentException e) {
      System.out.println("startingAt=" + startingAt + "; endingAt=" + endingAt);
      System.out.println("fComponentLimit=" + fComponentLimit);
      throw e;
    }

    fComponentStart = startingAt;
    fComponentLimit = endingAt;
    // debugFormatCount += (endingAt-startingAt);
  }