Package org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext

Source Code of org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.TextDocumentWriter

/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2001 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext;

import java.awt.print.Paper;
import java.io.IOException;

import org.pentaho.reporting.engine.classic.core.layout.model.BlockRenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.CanvasRenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.InlineRenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.LayoutNodeTypes;
import org.pentaho.reporting.engine.classic.core.layout.model.LogicalPageBox;
import org.pentaho.reporting.engine.classic.core.layout.model.PageGrid;
import org.pentaho.reporting.engine.classic.core.layout.model.ParagraphRenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.PhysicalPageBox;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderNode;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderableText;
import org.pentaho.reporting.engine.classic.core.layout.output.LogicalPageKey;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorMetaData;
import org.pentaho.reporting.engine.classic.core.layout.output.PhysicalPageKey;
import org.pentaho.reporting.engine.classic.core.layout.process.IterateStructuralProcessStep;
import org.pentaho.reporting.engine.classic.core.layout.process.RevalidateTextEllipseProcessStep;
import org.pentaho.reporting.engine.classic.core.layout.text.Glyph;
import org.pentaho.reporting.engine.classic.core.layout.text.GlyphList;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.driver.PlainTextPage;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.driver.PrinterDriver;
import org.pentaho.reporting.engine.classic.core.util.geom.StrictBounds;
import org.pentaho.reporting.engine.classic.core.util.geom.StrictGeomUtility;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys;
import org.pentaho.reporting.libraries.fonts.encoding.CodePointBuffer;

/**
* Creation-Date: 13.05.2007, 15:49:13
*
* @author Thomas Morgner
*/
public class TextDocumentWriter extends IterateStructuralProcessStep
{
  private PrinterDriver driver;
  private String encoding;
  private PlainTextPage plainTextPage;
  private long characterWidthInMicroPoint;
  private long characterHeightInMicroPoint;
  private StrictBounds drawArea;
  private RevalidateTextEllipseProcessStep revalidateTextEllipseProcessStep;
  private long contentAreaX1;
  private long contentAreaX2;
  private boolean textLineOverflow;
  private CodePointBuffer codePointBuffer;
  private boolean ellipseDrawn;
  private boolean clipOnWordBoundary;

  public TextDocumentWriter(final OutputProcessorMetaData metaData,
                            final PrinterDriver driver,
                            final String encoding)
  {
    if (encoding == null)
    {
      throw new NullPointerException();
    }
    if (driver == null)
    {
      throw new NullPointerException();
    }
    if (metaData == null)
    {
      throw new NullPointerException();
    }

    this.codePointBuffer = new CodePointBuffer(400);
    this.driver = driver;
    this.encoding = encoding;
    characterHeightInMicroPoint = StrictGeomUtility.toInternalValue(metaData.getNumericFeatureValue(
        TextOutputProcessorMetaData.CHAR_HEIGHT));
    characterWidthInMicroPoint = StrictGeomUtility.toInternalValue(metaData.getNumericFeatureValue(
        TextOutputProcessorMetaData.CHAR_WIDTH));

    if (characterHeightInMicroPoint <= 0 || characterWidthInMicroPoint <= 0)
    {
      throw new IllegalStateException("Invalid character box size. Cannot continue.");
    }
    revalidateTextEllipseProcessStep = new RevalidateTextEllipseProcessStep(metaData);
    this.clipOnWordBoundary = "true".equals
        (metaData.getConfiguration().getConfigProperty(
            "org.pentaho.reporting.engine.classic.core.LastLineBreaksOnWordBoundary"));
  }


  public void close()
  {
  }

  public void open()
  {

  }

  public void processPhysicalPage(final PageGrid pageGrid,
                                  final LogicalPageBox logicalPage,
                                  final int row,
                                  final int col,
                                  final PhysicalPageKey pageKey) throws IOException
  {
    final PhysicalPageBox page = pageGrid.getPage(row, col);
    final Paper paper = new Paper();
    paper.setSize(StrictGeomUtility.toExternalValue(page.getWidth()),
        StrictGeomUtility.toExternalValue(page.getHeight()));
    paper.setImageableArea
        (StrictGeomUtility.toExternalValue(page.getImageableX()),
            StrictGeomUtility.toExternalValue(page.getImageableY()),
            StrictGeomUtility.toExternalValue(page.getImageableWidth()),
            StrictGeomUtility.toExternalValue(page.getImageableHeight()));
    drawArea = new StrictBounds(page.getGlobalX(), page.getGlobalY(),
        page.getWidth(), page.getHeight());
    plainTextPage = new PlainTextPage(paper, driver, encoding);
    startProcessing(logicalPage);
    plainTextPage.writePage();
  }

  public void processLogicalPage(final LogicalPageKey key, final LogicalPageBox logicalPage) throws IOException
  {
    final Paper paper = new Paper();
    paper.setSize(StrictGeomUtility.toExternalValue(logicalPage.getPageWidth()),
        StrictGeomUtility.toExternalValue(logicalPage.getPageHeight()));
    paper.setImageableArea(0, 0,
        StrictGeomUtility.toExternalValue(logicalPage.getPageWidth()),
        StrictGeomUtility.toExternalValue(logicalPage.getPageHeight()));
    paper.setSize(logicalPage.getPageWidth(), logicalPage.getPageHeight());
    paper.setImageableArea(0, 0, logicalPage.getPageWidth(), logicalPage.getPageHeight());

    drawArea = new StrictBounds(0, 0, logicalPage.getWidth(), logicalPage.getHeight());
    plainTextPage = new PlainTextPage(paper, driver, encoding);
    startProcessing(logicalPage);
    plainTextPage.writePage();
  }

  protected boolean startBlockBox(final BlockRenderBox box)
  {
    if (box.getStaticBoxLayoutProperties().isVisible() == false)
    {
      return false;
    }

    if (box.isBoxVisible(drawArea) == false)
    {
      return false;
    }
    return true;
  }

  protected boolean startInlineBox(final InlineRenderBox box)
  {
    if (box.getStaticBoxLayoutProperties().isVisible() == false)
    {
      return false;
    }

    if (box.isBoxVisible(drawArea) == false)
    {
      return false;
    }
    return true;
  }

  public boolean startCanvasBox(final CanvasRenderBox box)
  {
    if (box.getStaticBoxLayoutProperties().isVisible() == false)
    {
      return false;
    }

    if (box.isBoxVisible(drawArea) == false)
    {
      return false;
    }
    return true;
  }

  protected boolean startRowBox(final RenderBox box)
  {
    if (box.getStaticBoxLayoutProperties().isVisible() == false)
    {
      return false;
    }

    if (box.isBoxVisible(drawArea) == false)
    {
      return false;
    }
    return true;
  }

  protected void drawText(final RenderableText renderableText)
  {
    drawText(renderableText, renderableText.getX() + renderableText.getWidth());
  }

  protected void drawText(final RenderableText text, final long contentX2)
  {
    if (text.isNodeVisible(drawArea) == false)
    {
      return;
    }
    if (text.getLength() == 0)
    {
      // This text is empty.
      return;
    }

    final GlyphList gs = text.getGlyphs();
    final int maxLength = computeMaximumTextSize(text, contentX2);
    final String rawText = gs.getText(text.getOffset(), maxLength, codePointBuffer);

    final int x = PlainTextPage.correctedDivisionFloor
        ((float) (text.getX() - drawArea.getX()), characterWidthInMicroPoint);
    final int y = PlainTextPage.correctedDivisionFloor
        ((float) (text.getY() - drawArea.getY()), characterHeightInMicroPoint);
    int w = Math.min(maxLength,
        PlainTextPage.correctedDivisionFloor((float) text.getWidth(), characterWidthInMicroPoint));

    // filter out results that do not belong to the current physical page
    if (x + w > plainTextPage.getWidth())
    {
      w = Math.max(0, plainTextPage.getWidth() - x);
    }
    if (w == 0)
    {
      return;
    }
    if (y < 0)
    {
      return;
    }
    if (y >= plainTextPage.getHeight())
    {
      return;
    }
    plainTextPage.addTextChunk(x, y, w, rawText, text.getStyleSheet());
  }

  protected int computeMaximumTextSize(final RenderableText node, final long contentX2)
  {
    final int length = node.getLength();
    final long x = node.getX();
    if (contentX2 >= (x + node.getWidth()))
    {
      return length;
    }

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

    for (int i = offset; i < maxPos; i++)
    {
      final Glyph g = gs.getGlyph(i);
      runningPos += g.getWidth();
      if (runningPos > contentX2)
      {
        return Math.max(0, i - offset);
      }
    }
    return length;
  }

  protected void processOtherNode(final RenderNode node)
  {
    if ((node.getNodeType() == LayoutNodeTypes.TYPE_NODE_TEXT) == false)
    {
      return;
    }

    if (isTextLineOverflow())
    {
      if (node.isNodeVisible(drawArea) == false)
      {
        return;
      }

      if (clipOnWordBoundary == false)
      {
        final RenderableText text = (RenderableText) node;
        final long ellipseSize = extractEllipseSize(node);
        final long x1 = text.getX();
        final long effectiveAreaX2 = (contentAreaX2 - ellipseSize);

        if (x1 >= contentAreaX2)
        {
          // Skip, the node will not be visible.
        }
        else
        {
          // The text node that is printed will overlap with the ellipse we need to print.
          drawText(text, effectiveAreaX2);
        }
      }

      if (node.isVirtualNode())
      {
        if (ellipseDrawn)
        {
          return;
        }
        ellipseDrawn = true;

        final RenderBox parent = node.getParent();
        if (parent != null)
        {
          final RenderBox textEllipseBox = parent.getTextEllipseBox();
          if (textEllipseBox != null)
          {
            processBoxChilds(textEllipseBox);
          }
        }
        return;
      }
    }

    if (isTextLineOverflow())
    {
      if (node.isNodeVisible(drawArea) == false)
      {
        return;
      }

      final long ellipseSize = extractEllipseSize(node);
      final long x1 = node.getX();
      final long x2 = x1 + node.getWidth();
      final long effectiveAreaX2 = (contentAreaX2 - ellipseSize);
      if (x2 <= effectiveAreaX2)
      {
        // the text will be fully visible.
        drawText((RenderableText) node);
      }
      else if (x1 >= contentAreaX2)
      {
        // Skip, the node will not be visible.
      }
      else
      {
        // The text node that is printed will overlap with the ellipse we need to print.
        drawText((RenderableText) node, effectiveAreaX2);
        final RenderBox parent = node.getParent();
        if (parent != null)
        {
          final RenderBox textEllipseBox = parent.getTextEllipseBox();
          if (textEllipseBox != null)
          {
            processBoxChilds(textEllipseBox);
          }
        }
      }

    }
    else
    {
      drawText((RenderableText) node);
    }
  }

  private long extractEllipseSize(final RenderNode node)
  {
    if (node == null)
    {
      return 0;
    }
    final RenderBox parent = node.getParent();
    if (parent == null)
    {
      return 0;
    }
    final RenderBox textEllipseBox = parent.getTextEllipseBox();
    if (textEllipseBox == null)
    {
      return 0;
    }
    return textEllipseBox.getWidth();
  }

  protected void processParagraphChilds(final ParagraphRenderBox box)
  {
    this.contentAreaX1 = box.getContentAreaX1();
    this.contentAreaX2 = box.getContentAreaX2();

    RenderBox lineBox = (RenderBox) box.getFirstChild();
    while (lineBox != null)
    {
      processTextLine(lineBox, contentAreaX1, contentAreaX2);
      lineBox = (RenderBox) lineBox.getNext();
    }
  }

  protected void processTextLine(final RenderBox lineBox,
                                 final long contentAreaX1,
                                 final long contentAreaX2)
  {
    final boolean overflowProperty = lineBox.getParent().getStaticBoxLayoutProperties().isOverflowX();
    this.textLineOverflow =
        ((lineBox.getX() + lineBox.getWidth()) > contentAreaX2) && overflowProperty == false;

    this.ellipseDrawn = false;
    if (textLineOverflow)
    {
      revalidateTextEllipseProcessStep.compute(lineBox, contentAreaX1, contentAreaX2);
    }

    startProcessing(lineBox);
  }

  public long getContentAreaX2()
  {
    return contentAreaX2;
  }

  public void setContentAreaX2(final long contentAreaX2)
  {
    this.contentAreaX2 = contentAreaX2;
  }

  public long getContentAreaX1()
  {
    return contentAreaX1;
  }

  public void setContentAreaX1(final long contentAreaX1)
  {
    this.contentAreaX1 = contentAreaX1;
  }

  public boolean isTextLineOverflow()
  {
    return textLineOverflow;
  }

  public void setTextLineOverflow(final boolean textLineOverflow)
  {
    this.textLineOverflow = textLineOverflow;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.TextDocumentWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.