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: * FillFlowPagesStep.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 a paginated copy of the logical page box. The headers and
038: * footers are properly aligned and the page's content area is extended to include these headers.
039: * <p/>
040: * Unlike the paginating 'FillPhysicalPagesStep', the header and footer areas were not taken into account during the
041: * ordinary pagination and so the resulting page will be larger than the incomming page.
042: *
043: * @author Thomas Morgner
044: */
045: public final class FillFlowPagesStep extends IterateVisualProcessStep {
046: private long contentEnd;
047: private long contentStart;
048:
049: public FillFlowPagesStep() {
050: }
051:
052: public LogicalPageBox compute(final LogicalPageBox pagebox,
053: final long pageStart, final long pageEnd) {
054: this .contentStart = pagebox.getHeaderArea().getHeight();
055: this .contentEnd = (pageEnd - pageStart) + contentStart;
056:
057: // This is a simple strategy.
058: // Copy and relocate, then prune. (I whished we could prune first, but
059: // this does not work.)
060: //
061: // For the sake of efficiency, we do *not* create private copies for each
062: // physical page. This would be an total overkill.
063: final LogicalPageBox derived = (LogicalPageBox) pagebox
064: .derive(true);
065:
066: // first, shift the normal-flow content downwards.
067: // The start of the logical pagebox might be in the negative range now
068: // The header-size has already been taken into account by the pagination
069: // step.
070: BoxShifter
071: .shiftBoxUnchecked(derived, -pageStart + contentStart);
072:
073: // now remove all the content that will not be visible at all ..
074: // not processing the header and footer area: they are 'out-of-context' bands
075: processBoxChilds(derived);
076:
077: // Then add the header at the top - it starts at (0,0) and thus it is
078: // ok to leave it unshifted.
079:
080: // finally, move the footer at the bottom (to the page's bottom, please!)
081: final RenderBox footerArea = derived.getFooterArea();
082: final long footerShift = contentEnd - footerArea.getY();
083: BoxShifter.shiftBoxUnchecked(footerArea, footerShift);
084:
085: // the renderer is responsible for painting the page-header and footer ..
086:
087: derived.setPageOffset(0);
088: derived.setPageEnd(contentEnd + footerArea.getY()
089: + footerArea.getHeight());
090: return derived;
091: }
092:
093: protected void processParagraphChilds(final ParagraphRenderBox box) {
094: processBoxChilds(box);
095: }
096:
097: /**
098: * Invisible nodes may need special treatment here.
099: *
100: * @param box
101: * @return
102: */
103: protected boolean startBlockLevelBox(final RenderBox box) {
104: RenderNode node = box.getFirstChild();
105: while (node != null) {
106: if (node.isIgnorableForRendering()) {
107: node = node.getNext();
108: continue;
109: }
110: // Special treatment for lines, which have a height of zero.
111: if (node.getY() == contentStart && node.getHeight() == 0) {
112: node = node.getNext();
113: } else if ((node.getY() + node.getHeight()) <= contentStart) {
114: final RenderNode next = node.getNext();
115: box.remove(node);
116: node = next;
117: } else if (node.getY() > contentEnd) {
118: final RenderNode next = node.getNext();
119: box.remove(node);
120: node = next;
121: } else {
122: node = node.getNext();
123: }
124: }
125: return true;
126: }
127:
128: protected boolean startCanvasLevelBox(final RenderBox box) {
129: RenderNode node = box.getFirstChild();
130: while (node != null) {
131: if (node.isIgnorableForRendering()) {
132: node = node.getNext();
133: continue;
134: }
135: // Special treatment for lines, which have a height of zero.
136: if (node.getY() == contentStart && node.getHeight() == 0) {
137: node = node.getNext();
138: } else if ((node.getY() + node.getHeight()) <= contentStart) {
139: final RenderNode next = node.getNext();
140: box.remove(node);
141: node = next;
142: } else if (node.getY() >= contentEnd) {
143: final RenderNode next = node.getNext();
144: box.remove(node);
145: node = next;
146: } else {
147: node = node.getNext();
148: }
149: }
150: return true;
151: }
152: }
|