protected boolean startBox(final RenderBox box) {
   if (isValidDrawTarget(box)) {
     if (bounds == null) {
       bounds = new StrictBounds(box.getX(), box.getY(), box.getWidth(), box.getHeight());
     } else {
       bounds.add(box.getX(), box.getY(), box.getWidth(), box.getHeight());
     }
   }
   return true;
 }
  private void assertPageValid(final List<LogicalPageBox> pages, final int page, final long offset)
      throws Exception {
    final LogicalPageBox pageBox = pages.get(page);
    final long pageOffset = pageBox.getPageOffset();

    // ModelPrinter.INSTANCE.print(pageBox);

    final RenderNode[] elementsByNodeType =
        MatchFactory.findElementsByNodeType(pageBox, LayoutNodeTypes.TYPE_BOX_TABLE_SECTION);
    Assert.assertEquals(2, elementsByNodeType.length);
    final TableSectionRenderBox header = (TableSectionRenderBox) elementsByNodeType[0];
    Assert.assertEquals(TableSectionRenderBox.Role.HEADER, header.getDisplayRole());
    final TableSectionRenderBox body = (TableSectionRenderBox) elementsByNodeType[1];
    Assert.assertEquals(TableSectionRenderBox.Role.BODY, body.getDisplayRole());
    final RenderNode[] rows =
        MatchFactory.findElementsByNodeType(body, LayoutNodeTypes.TYPE_BOX_TABLE_ROW);
    Assert.assertTrue("Have rows on page " + page, rows.length > 0);

    Assert.assertEquals("Header starts at top of page " + page, pageOffset + offset, header.getY());
    Assert.assertEquals(
        "Row starts after the header on page " + page,
        header.getY() + header.getHeight(),
        rows[0].getY());

    final RenderNode[] table =
        MatchFactory.findElementsByNodeType(pageBox, LayoutNodeTypes.TYPE_BOX_TABLE);
    Assert.assertEquals(1, table.length);
    final RenderBox box = (RenderBox) table[0];
    final RenderNode lastChild = box.getLastChild();
    Assert.assertEquals(
        "Table height extends correctly on page " + page,
        box.getY() + box.getHeight(),
        lastChild.getY() + lastChild.getHeight());
  }
  public void testWeirdTocLayout() throws ReportProcessingException, ContentProcessingException {
    Element textField = new Element();
    textField.setName("textField");
    textField.getStyle().setStyleProperty(TextStyleKeys.FONT, "Arial");
    textField.getStyle().setStyleProperty(TextStyleKeys.FONTSIZE, 14);
    textField.getStyle().setStyleProperty(TextStyleKeys.TEXT_WRAP, TextWrap.NONE);
    textField.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, 97f);
    textField.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, 20f);
    textField.getStyle().setStyleProperty(ElementStyleKeys.POS_X, 0f);
    textField.getStyle().setStyleProperty(ElementStyleKeys.POS_Y, 0f);
    textField.setElementType(LabelType.INSTANCE);
    textField.setAttribute(
        AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, "Classic Cars");

    Element dotField = new Element();
    dotField.setName("dotField");
    dotField.getStyle().setStyleProperty(TextStyleKeys.FONT, "Arial");
    dotField.getStyle().setStyleProperty(TextStyleKeys.FONTSIZE, 14);
    dotField.getStyle().setStyleProperty(ElementStyleKeys.ALIGNMENT, ElementAlignment.RIGHT);
    dotField.getStyle().setStyleProperty(ElementStyleKeys.VALIGNMENT, ElementAlignment.TOP);
    dotField.getStyle().setStyleProperty(ElementStyleKeys.POS_X, 97f);
    dotField.getStyle().setStyleProperty(ElementStyleKeys.POS_Y, 0f);
    dotField.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, 628.463f);
    dotField.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, 20f);
    dotField.getStyle().setStyleProperty(ElementStyleKeys.WIDTH, 100f);
    dotField.getStyle().setStyleProperty(ElementStyleKeys.MAX_WIDTH, 100f);
    dotField.setElementType(LabelType.INSTANCE);
    dotField.setAttribute(
        AttributeNames.Core.NAMESPACE,
        AttributeNames.Core.VALUE,
        " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
            + " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
            + ". . . . . . . . . . . . . . . . . .");

    Band band = new Band();
    band.setName("outer-box");
    band.setLayout("inline");
    band.getStyle().setStyleProperty(ElementStyleKeys.BOX_SIZING, BoxSizing.CONTENT_BOX);
    band.getStyle().setStyleProperty(ElementStyleKeys.OVERFLOW_X, false);
    band.getStyle().setStyleProperty(ElementStyleKeys.OVERFLOW_Y, false);
    band.getStyle().setStyleProperty(TextStyleKeys.LINEHEIGHT, 1f);
    band.getStyle()
        .setStyleProperty(TextStyleKeys.WHITE_SPACE_COLLAPSE, WhitespaceCollapse.PRESERVE_BREAKS);
    band.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, 708f);
    band.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, 12f);
    band.getStyle().setStyleProperty(ElementStyleKeys.MAX_HEIGHT, 20f);
    band.addElement(textField);
    band.addElement(dotField);

    final MasterReport report = new MasterReport();
    report.getReportHeader().addElement(band);

    LogicalPageBox logicalPageBox =
        DebugReportRunner.layoutSingleBand(report, report.getReportHeader(), false, false);
    // ModelPrinter.INSTANCE.print(logicalPageBox);

    RenderBox outerBox = (RenderBox) MatchFactory.findElementByName(logicalPageBox, "outer-box");
    RenderNode dotFieldBox = MatchFactory.findElementByName(logicalPageBox, "dotField");
    RenderNode textFieldBox = MatchFactory.findElementByName(logicalPageBox, "textField");
    assertNotNull(outerBox);
    assertNotNull(dotFieldBox);
    assertNotNull(textFieldBox);

    assertEquals(0, outerBox.getY());
    assertEquals(0, dotFieldBox.getY());
    assertEquals(0, textFieldBox.getY());

    // box only contains one line, and min-size is set to 8, max size = 20, so the line-height of
    // 14.024 is used.
    assertEquals(StrictGeomUtility.toInternalValue(14.024), outerBox.getHeight());
    assertEquals(StrictGeomUtility.toInternalValue(14.024), outerBox.getFirstChild().getHeight());
    assertEquals(StrictGeomUtility.toInternalValue(14), dotFieldBox.getHeight());
    assertEquals(StrictGeomUtility.toInternalValue(14), textFieldBox.getHeight());
  }
Пример #4
0
  /** @noinspection IOResourceOpenedButNotSafelyClosed */
  public void print(
      final LogicalPageKey logicalPageKey,
      final LogicalPageBox logicalPage,
      final TableContentProducer contentProducer,
      final RTFOutputProcessorMetaData metaData,
      final boolean incremental)
      throws ContentProcessingException {
    final int startRow = contentProducer.getFinishedRows();
    final int finishRow = contentProducer.getFilledRows();
    if (incremental && startRow == finishRow) {
      return;
    }

    if (document == null) {
      this.cellBackgroundProducer =
          new CellBackgroundProducer(
              metaData.isFeatureSupported(AbstractTableOutputProcessor.TREAT_ELLIPSE_AS_RECTANGLE),
              metaData.isFeatureSupported(OutputProcessorFeature.UNALIGNED_PAGEBANDS));

      final PhysicalPageBox pageFormat = logicalPage.getPageGrid().getPage(0, 0);
      final float urx = (float) StrictGeomUtility.toExternalValue(pageFormat.getWidth());
      final float ury = (float) StrictGeomUtility.toExternalValue(pageFormat.getHeight());

      final float marginLeft =
          (float) StrictGeomUtility.toExternalValue(pageFormat.getImageableX());
      final float marginRight =
          (float)
              StrictGeomUtility.toExternalValue(
                  pageFormat.getWidth()
                      - pageFormat.getImageableWidth()
                      - pageFormat.getImageableX());
      final float marginTop = (float) StrictGeomUtility.toExternalValue(pageFormat.getImageableY());
      final float marginBottom =
          (float)
              StrictGeomUtility.toExternalValue(
                  pageFormat.getHeight()
                      - pageFormat.getImageableHeight()
                      - pageFormat.getImageableY());
      final Rectangle pageSize = new Rectangle(urx, ury);

      document = new Document(pageSize, marginLeft, marginRight, marginTop, marginBottom);
      imageCache = new RTFImageCache(resourceManager);

      // rtf does not support PageFormats or other meta data...
      final PatchRtfWriter2 instance =
          PatchRtfWriter2.getInstance(document, new NoCloseOutputStream(outputStream));
      instance.getDocumentSettings().setAlwaysUseUnicode(true);

      final String author =
          config.getConfigProperty(
              "org.pentaho.reporting.engine.classic.core.modules.output.table.rtf.Author");
      if (author != null) {
        document.addAuthor(author);
      }

      final String title =
          config.getConfigProperty(
              "org.pentaho.reporting.engine.classic.core.modules.output.table.rtf.Title");
      if (title != null) {
        document.addTitle(title);
      }

      document.addProducer();
      document.addCreator(RTFPrinter.CREATOR);

      try {
        document.addCreationDate();
      } catch (Exception e) {
        RTFPrinter.logger.debug("Unable to add creation date. It will have to work without it.", e);
      }

      document.open();
    }

    // Start a new page.
    try {
      final SheetLayout sheetLayout = contentProducer.getSheetLayout();
      final int columnCount = contentProducer.getColumnCount();
      if (table == null) {
        final int rowCount = contentProducer.getRowCount();
        table = new Table(columnCount, rowCount);
        table.setAutoFillEmptyCells(false);
        table.setWidth(100); // span the full page..
        // and finally the content ..

        final float[] cellWidths = new float[columnCount];
        for (int i = 0; i < columnCount; i++) {
          cellWidths[i] =
              (float) StrictGeomUtility.toExternalValue(sheetLayout.getCellWidth(i, i + 1));
        }
        table.setWidths(cellWidths);
      }

      // logger.debug ("Processing: " + startRow + " " + finishRow + " " + incremental);

      for (int row = startRow; row < finishRow; row++) {
        for (short col = 0; col < columnCount; col++) {
          final RenderBox content = contentProducer.getContent(row, col);
          final CellMarker.SectionType sectionType = contentProducer.getSectionType(row, col);

          if (content == null) {
            final RenderBox backgroundBox = contentProducer.getBackground(row, col);
            final CellBackground background;
            if (backgroundBox != null) {
              background =
                  cellBackgroundProducer.getBackgroundForBox(
                      logicalPage, sheetLayout, col, row, 1, 1, true, sectionType, backgroundBox);
            } else {
              background =
                  cellBackgroundProducer.getBackgroundAt(
                      logicalPage, sheetLayout, col, row, true, sectionType);
            }
            if (background == null) {
              // An empty cell .. ignore
              final PatchRtfCell cell = new PatchRtfCell();
              cell.setBorderWidth(0);
              cell.setMinimumHeight(
                  (float) StrictGeomUtility.toExternalValue(sheetLayout.getRowHeight(row)));
              table.addCell(cell, row, col);
              continue;
            }

            // A empty cell with a defined background ..
            final PatchRtfCell cell = new PatchRtfCell();
            cell.setBorderWidth(0);
            cell.setMinimumHeight(
                (float) StrictGeomUtility.toExternalValue(sheetLayout.getRowHeight(row)));
            updateCellStyle(cell, background);
            table.addCell(cell, row, col);
            continue;
          }

          if (content.isCommited() == false) {
            throw new InvalidReportStateException("Uncommited content encountered");
          }

          final long contentOffset = contentProducer.getContentOffset(row, col);
          final long colPos = sheetLayout.getXPosition(col);
          final long rowPos = sheetLayout.getYPosition(row);
          if (content.getX() != colPos || (content.getY() + contentOffset) != rowPos) {
            // A spanned cell ..
            continue;
          }

          final int colSpan = sheetLayout.getColSpan(col, content.getX() + content.getWidth());
          final int rowSpan =
              sheetLayout.getRowSpan(row, content.getY() + content.getHeight() + contentOffset);

          final CellBackground realBackground =
              cellBackgroundProducer.getBackgroundForBox(
                  logicalPage,
                  sheetLayout,
                  col,
                  row,
                  colSpan,
                  rowSpan,
                  false,
                  sectionType,
                  content);

          final PatchRtfCell cell = new PatchRtfCell();
          cell.setRowspan(rowSpan);
          cell.setColspan(colSpan);
          cell.setBorderWidth(0);
          cell.setMinimumHeight(
              (float) StrictGeomUtility.toExternalValue(sheetLayout.getRowHeight(row)));
          if (realBackground != null) {
            updateCellStyle(cell, realBackground);
          }

          computeCellStyle(content, cell);

          // export the cell and all content ..
          final RTFTextExtractor etx = new RTFTextExtractor(metaData);
          etx.compute(content, cell, imageCache);

          table.addCell(cell, row, col);
          content.setFinishedTable(true);
          // logger.debug("set Finished to cell (" + col + ", " + row + "," + content.getName() +
          // ")");
        }
      }

      if (incremental == false) {
        document.add(table);
        table = null;
      }
    } catch (DocumentException e) {
      throw new ContentProcessingException("Failed to generate RTF-Document", e);
    }
  }