001: /**
002: * ===========================================
003: * JFreeReport : a free Java reporting library
004: * ===========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
009: *
010: * This library is free software; you can redistribute it and/or modify it under the terms
011: * of the GNU Lesser General Public License as published by the Free Software Foundation;
012: * either version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: * See the GNU Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public License along with this
019: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: *
022: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023: * in the United States and other countries.]
024: *
025: * ------------
026: * FillPhysicalPagesStep.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.layout.process;
030:
031: import org.jfree.report.layout.model.LogicalPageBox;
032: import org.jfree.report.layout.model.ParagraphRenderBox;
033: import org.jfree.report.layout.model.RenderBox;
034: import org.jfree.report.layout.model.RenderNode;
035:
036: /**
037: * This Step copies all content from the logical page into the page-grid. When done, it clears the content and replaces
038: * the elements with dummy-nodes. These nodes have a fixed-size (the last known layouted size), and will not be
039: * recomputed later.
040: * <p/>
041: * Adjoining dummy-nodes get unified into a single node, thus simplifying and pruning the document tree.
042: *
043: * @author Thomas Morgner
044: */
045: public final class FillPhysicalPagesStep extends
046: IterateVisualProcessStep {
047: private long contentEnd;
048: private long contentStart;
049:
050: public FillPhysicalPagesStep() {
051: }
052:
053: public LogicalPageBox compute(final LogicalPageBox pagebox,
054: final long pageStart, final long pageEnd) {
055: this .contentStart = pagebox.getHeaderArea().getHeight();
056: this .contentEnd = (pageEnd - pageStart) + contentStart;
057:
058: // This is a simple strategy.
059: // Copy and relocate, then prune. (I whished we could prune first, but
060: // this does not work.)
061: //
062: // For the sake of efficiency, we do *not* create private copies for each
063: // physical page. This would be an total overkill.
064: final LogicalPageBox derived = (LogicalPageBox) pagebox
065: .derive(true);
066:
067: // first, shift the normal-flow content downwards.
068: // The start of the logical pagebox might be in the negative range now
069: // The header-size has already been taken into account by the pagination
070: // step.
071: BoxShifter
072: .shiftBoxUnchecked(derived, -pageStart + contentStart);
073:
074: // now remove all the content that will not be visible at all ..
075: // not processing the header and footer area: they are 'out-of-context' bands
076: processBoxChilds(derived);
077:
078: // Then add the header at the top - it starts at (0,0) and thus it is
079: // ok to leave it unshifted.
080:
081: // finally, move the footer at the bottom (to the page's bottom, please!)
082: final RenderBox footerArea = derived.getFooterArea();
083: final long footerPosition = pagebox.getPageHeight()
084: - (footerArea.getY() + footerArea.getHeight());
085: final long footerShift = footerPosition - footerArea.getY();
086: BoxShifter.shiftBoxUnchecked(footerArea, footerShift);
087:
088: // the renderer is responsible for painting the page-header and footer ..
089:
090: derived.setPageOffset(0);
091: derived.setPageEnd(contentEnd);
092: return derived;
093: }
094:
095: protected void processParagraphChilds(final ParagraphRenderBox box) {
096: processBoxChilds(box);
097: }
098:
099: /**
100: * Invisible nodes may need special treatment here.
101: *
102: * @param box
103: * @return
104: */
105: protected boolean startBlockLevelBox(final RenderBox box) {
106: RenderNode node = box.getFirstChild();
107: while (node != null) {
108: if (node.isIgnorableForRendering()) {
109: node = node.getNext();
110: continue;
111: }
112:
113: // Special treatment for lines, which have a height of zero.
114: if (node.getY() == contentStart && node.getHeight() == 0) {
115: node = node.getNext();
116: } else if ((node.getY() + node.getHeight()) <= contentStart) {
117: final RenderNode next = node.getNext();
118: box.remove(node);
119: node = next;
120: } else if (node.getY() >= contentEnd) {
121: final RenderNode next = node.getNext();
122: box.remove(node);
123: node = next;
124: } else {
125: node = node.getNext();
126: }
127: }
128: return true;
129: }
130:
131: protected boolean startCanvasLevelBox(final RenderBox box) {
132: RenderNode node = box.getFirstChild();
133: while (node != null) {
134: if (node.isIgnorableForRendering()) {
135: node = node.getNext();
136: continue;
137: }
138: // Special treatment for lines, which have a height of zero.
139: if (node.getY() == contentStart && node.getHeight() == 0) {
140: node = node.getNext();
141: } else if ((node.getY() + node.getHeight()) <= contentStart) {
142: final RenderNode next = node.getNext();
143: box.remove(node);
144: node = next;
145: } else if (node.getY() >= contentEnd) {
146: final RenderNode next = node.getNext();
147: box.remove(node);
148: node = next;
149: } else {
150: node = node.getNext();
151: }
152: }
153: return true;
154: }
155: }
|