protected void computeInlineBlock(
      final RenderBox box, final long position, final long itemElementWidth) {
    final StaticBoxLayoutProperties blp = box.getStaticBoxLayoutProperties();
    box.setCachedX(position + blp.getMarginLeft());
    final long width = itemElementWidth - blp.getMarginLeft() - blp.getMarginRight();
    if (width == 0) {
      // ModelPrinter.printParents(box);

      throw new IllegalStateException(
          "A box without any width? "
              + Integer.toHexString(System.identityHashCode(box))
              + ' '
              + box.getClass());
    }
    box.setCachedWidth(width);

    final BoxDefinition bdef = box.getBoxDefinition();
    final long leftInsets = bdef.getPaddingLeft() + blp.getBorderLeft();
    final long rightInsets = bdef.getPaddingRight() + blp.getBorderRight();
    box.setContentAreaX1(box.getCachedX() + leftInsets);
    box.setContentAreaX2(box.getCachedX() + box.getCachedWidth() - rightInsets);

    //    final InfiniteMinorAxisLayoutStep layoutStep = new InfiniteMinorAxisLayoutStep(metaData);
    //    layoutStep.continueComputation(getPageGrid(), box);
  }
  protected void finishRowBox(final RenderBox box) {
    if (box.getStaticBoxLayoutProperties().isVisible() == false) {
      return;
    }

    textExtractorHelper.finishBox(box.getInstanceId(), box.getAttributes());
  }
  /**
   * Like a canvas box, a row-box should be split into several cells already. Therefore we treat it
   * as a generic content container instead.
   */
  protected boolean startRowBox(final RenderBox box) {
    if (box.getStaticBoxLayoutProperties().isVisible() == false) {
      return false;
    }

    return textExtractorHelper.startBox(
        box.getInstanceId(),
        box.getAttributes(),
        box.getStyleSheet(),
        box.getBoxDefinition(),
        true);
  }
 private void ensureEmptyChildIsAdded(final RenderBox parent, final ReportElement element) {
   final StyleSheet resolverStyleSheet = element.getComputedStyle();
   final RenderBox box;
   if (parent.isAcceptInlineBoxes()) {
     box =
         renderNodeFactory.produceRenderBox(
             element, resolverStyleSheet, BandStyleKeys.LAYOUT_INLINE, getStateKey());
   } else {
     box =
         renderNodeFactory.produceRenderBox(
             element, resolverStyleSheet, BandStyleKeys.LAYOUT_BLOCK, getStateKey());
   }
   box.getStaticBoxLayoutProperties()
       .setPlaceholderBox(StaticBoxLayoutProperties.PlaceholderType.SECTION);
   box.close();
   parent.addChild(box);
 }
  public void startSubFlow(final ReportElement element) {
    final StyleSheet resolverStyleSheet = element.getComputedStyle();

    final RenderBox box;
    if (metaData.isFeatureSupported(OutputProcessorFeature.STRICT_COMPATIBILITY)) {
      final StyleSheet styleSheet =
          new SubReportStyleSheet(
              resolverStyleSheet.getBooleanStyleProperty(BandStyleKeys.PAGEBREAK_BEFORE),
              (resolverStyleSheet.getBooleanStyleProperty(BandStyleKeys.PAGEBREAK_AFTER)));

      final SimpleStyleSheet reportStyle = new SimpleStyleSheet(styleSheet);
      final BoxDefinition boxDefinition = renderNodeFactory.getBoxDefinition(reportStyle);
      box =
          new BlockRenderBox(
              reportStyle,
              element.getObjectID(),
              boxDefinition,
              SubReportType.INSTANCE,
              element.getAttributes(),
              null);
    } else {
      box =
          renderNodeFactory.produceRenderBox(
              element, resolverStyleSheet, BandStyleKeys.LAYOUT_BLOCK, stateKey);
    }

    box.getStaticBoxLayoutProperties()
        .setPlaceholderBox(StaticBoxLayoutProperties.PlaceholderType.SECTION);
    if (element.getName() != null) {
      box.setName("Banded-SubReport-Section" + ": name=" + element.getName());
    } else {
      box.setName("Banded-SubReport-Section");
    }

    pushBoxToContext(box, false);
  }
  public RenderBox next() {
    cleanFirstSpacers();

    Arrays.fill(elementDimensions, 0);
    Arrays.fill(elementPositions, 0);

    int lastPosition = iterate(sequenceElements, sequenceFill);
    if (lastPosition == 0) {
      // This could evolve into an infinite loop. Thats evil.
      // We have two choices to prevent that:
      // (1) Try to break the element.
      //      if (getBreakableIndex() >= 0)
      //      {
      //        // Todo: Breaking is not yet implemented ..
      //      }
      if (getSkipIndex() >= 0) {
        // This causes an overflow ..
        performSkipAlignment(getSkipIndex());
        lastPosition = getSkipIndex();
      } else {
        // Skip the complete line. Oh, thats not good, really!
        lastPosition = sequenceFill;
      }
    }

    // now, build the line and update the array ..
    pendingElements.clear();
    contexts.clear();
    RenderBox firstBox = null;
    RenderBox box = null;
    for (int i = 0; i < lastPosition; i++) {
      final RenderNode node = nodes[i];
      final InlineSequenceElement element = sequenceElements[i];
      if (element instanceof EndSequenceElement) {
        contexts.pop();
        final long boxX2 = (elementPositions[i] + elementDimensions[i]);
        box.setCachedWidth(boxX2 - box.getCachedX());

        if (contexts.isEmpty()) {
          box = null;
        } else {
          final RenderNode tmpnode = box;
          box = contexts.peek();
          box.addGeneratedChild(tmpnode);
        }
        continue;
      }

      if (element instanceof StartSequenceElement) {
        box = (RenderBox) node.derive(false);
        box.setCachedX(elementPositions[i]);
        contexts.push(box);
        if (firstBox == null) {
          firstBox = box;
        }
        continue;
      }

      if (box == null) {
        throw new IllegalStateException(
            "Invalid sequence: " + "Cannot have elements before we open the box context.");
      }

      // Content element: Perform a deep-deriveForAdvance, so that we preserve the
      // possibly existing sub-nodes.
      final RenderNode child = node.derive(true);
      child.setCachedX(elementPositions[i]);
      child.setCachedWidth(elementDimensions[i]);
      if (box.getStaticBoxLayoutProperties().isPreserveSpace()
          && box.getStyleSheet().getBooleanStyleProperty(TextStyleKeys.TRIM_TEXT_CONTENT)
              == false) {
        // Take a shortcut as we know that we will never have any pending elements if preserve is
        // true and
        // trim-content is false.
        box.addGeneratedChild(child);
        continue;
      }

      if (child.isIgnorableForRendering()) {
        pendingElements.add(child);
      } else {
        for (int j = 0; j < pendingElements.size(); j++) {
          final RenderNode pendingNode = pendingElements.get(j);
          box.addGeneratedChild(pendingNode);
        }
        pendingElements.clear();
        box.addGeneratedChild(child);
      }
    }

    // Remove all spacers and other non printable content that might
    // look ugly at the beginning of a new line ..
    for (; lastPosition < sequenceFill; lastPosition++) {
      final RenderNode node = nodes[lastPosition];
      final StyleSheet styleSheet = node.getStyleSheet();
      if (WhitespaceCollapse.PRESERVE.equals(
              styleSheet.getStyleProperty(TextStyleKeys.WHITE_SPACE_COLLAPSE))
          && styleSheet.getBooleanStyleProperty(TextStyleKeys.TRIM_TEXT_CONTENT) == false) {
        break;
      }

      if (node.isIgnorableForRendering() == false) {
        break;
      }
    }

    // If there are open contexts, then add the split-result to the new line
    // and update the width of the current line
    RenderBox previousContext = null;
    final int openContexts = contexts.size();
    for (int i = 0; i < openContexts; i++) {
      final RenderBox renderBox = contexts.get(i);
      final long cachedWidth = getEndOfLine() - renderBox.getCachedX();
      renderBox.setCachedWidth(cachedWidth);

      final InlineRenderBox rightBox =
          (InlineRenderBox) renderBox.split(RenderNode.HORIZONTAL_AXIS);
      sequenceElements[i] = StartSequenceElement.INSTANCE;
      nodes[i] = rightBox;
      if (previousContext != null) {
        previousContext.addGeneratedChild(renderBox);
      }
      previousContext = renderBox;
    }

    final int length = sequenceFill - lastPosition;
    System.arraycopy(sequenceElements, lastPosition, sequenceElements, openContexts, length);
    System.arraycopy(nodes, lastPosition, nodes, openContexts, length);
    sequenceFill = openContexts + length;
    Arrays.fill(sequenceElements, sequenceFill, sequenceElements.length, null);
    Arrays.fill(nodes, sequenceFill, nodes.length, null);

    return firstBox;
  }