builder.addMapping(uri, "instream-foreign-object", InstreamForeignObject.maker());
builder.addMapping(uri, "leader", Leader.maker());
builder.addMapping(uri, "character", org.apache.fop.fo.flow.Character.maker());
+ builder.addMapping(uri, "footnote", Footnote.maker());
+ builder.addMapping(uri, "footnote-body", FootnoteBody.maker());
}
}
startIndent += bodyIndent + distanceBetweenStarts;
}
- area.getIDReferences().createID(id);
+ if(area.getIDReferences() != null)
+ area.getIDReferences().createID(id);
this.marker = 0;
if (((FOText) fo).willCreateArea()) {
fo.setWidows(blockWidows);
break;
+ } else {
+ children.removeElementAt(i);
+ numChildren = this.children.size();
+ i--;
}
} else {
fo.setWidows(blockWidows);
}
}
- for (int i = numChildren - 1; i > 0; i--) {
+ for (int i = numChildren - 1; i >= 0; i--) {
FONode fo = (FONode) children.elementAt(i);
if (fo instanceof FOText) {
if (((FOText) fo).willCreateArea()) {
this.textIndent = 0;
}
- if (marker == 0) {
+ if (marker == 0 && area.getIDReferences() != null) {
area.getIDReferences().configureID(id, area);
}
+ int spaceLeft = area.spaceLeft();
this.blockArea = new BlockArea(fs, area.getAllocationWidth(),
area.spaceLeft(), startIndent, endIndent, textIndent,
align, alignLast, lineHeight);
if ((i != 0)) {
status = new Status(Status.AREA_FULL_SOME);
area.addChild(blockArea);
+ area.setMaxHeight(area.getMaxHeight() - spaceLeft + blockArea.getMaxHeight());
area.increaseHeight(blockArea.getHeight());
area.setAbsoluteHeight(
blockArea.getAbsoluteHeight());
//blockArea.end();
area.addChild(blockArea);
+ area.setMaxHeight(area.getMaxHeight() - spaceLeft + blockArea.getMaxHeight());
area.increaseHeight(blockArea.getHeight());
area.setAbsoluteHeight(blockArea.getAbsoluteHeight());
anythingLaidOut = true;
// flow is *always* laid out into a BodyAreaContainer
BodyAreaContainer bac = (BodyAreaContainer)area;
-
+
boolean prevChildMustKeepWithNext = false;
-
+ Vector pageMarker = this.getMarkerSnapshot(new Vector());
+
int numChildren = this.children.size();
for (int i = this.marker; i < numChildren; i++) {
FObj fo = (FObj) children.elementAt(i);
}
_status = fo.layout(currentArea);
+
+/* if((_status.isPageBreak() || i == numChildren - 1) && bac.needsFootnoteAdjusting()) {
+ bac.adjustFootnoteArea();
+ this.rollback(pageMarker);
+ i = this.marker - 1;
+ Area mainReferenceArea = bac.getMainReferenceArea();
+ // remove areas
+ continue;
+ }*/
if (_status.isIncomplete()) {
if ((prevChildMustKeepWithNext) && (_status.laidOutNone())) {
this.marker = i - 1;
--- /dev/null
+/*-- $Id$ --
+
+ ============================================================================
+ The Apache Software License, Version 1.1
+ ============================================================================
+
+ Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modifica-
+ tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. The end-user documentation included with the redistribution, if any, must
+ include the following acknowledgment: "This product includes software
+ developed by the Apache Software Foundation (http://www.apache.org/)."
+ Alternately, this acknowledgment may appear in the software itself, if
+ and wherever such third-party acknowledgments normally appear.
+
+ 4. The names "FOP" and "Apache Software Foundation" must not be used to
+ endorse or promote products derived from this software without prior
+ written permission. For written permission, please contact
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation and was originally created by
+ James Tauber <jtauber@jtauber.com>. For more information on the Apache
+ Software Foundation, please see <http://www.apache.org/>.
+
+ */
+
+package org.apache.fop.fo.flow;
+
+// FOP
+import org.apache.fop.fo.*;
+import org.apache.fop.layout.*;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.properties.*;
+import org.apache.fop.messaging.*;
+
+// Java
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class Footnote extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new Footnote(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new Footnote.Maker();
+ }
+
+ public Footnote(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:footnote";
+ }
+
+ public Status layout(Area area) throws FOPException {
+ FONode inline = null;
+ FONode fbody = null;
+ if(this.marker == START) {
+ this.marker = 0;
+ }
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ FONode fo = (FONode) children.elementAt(i);
+ if(fo instanceof Inline) {
+ inline = fo;
+ Status status = fo.layout(area);
+ if(status.isIncomplete()) {
+ return status;
+ }
+ } else if(inline != null && fo instanceof FootnoteBody) {
+ // add footnote to current page or next if it can't fit
+ fbody = fo;
+ if(area instanceof BlockArea) {
+ ((BlockArea)area).addFootnote((FootnoteBody)fbody);
+ } else {
+ Page page = area.getPage();
+ layoutFootnote(page, (FootnoteBody)fbody, area);
+ }
+ }
+ }
+ if(fbody == null) {
+ MessageHandler.errorln("WARNING: no footnote-body in footnote");
+ }
+ if (area instanceof BlockArea) {
+ }
+ return new Status(Status.OK);
+ }
+
+ public static boolean layoutFootnote(Page p, FootnoteBody fb, Area area)
+ {
+ try {
+ BodyAreaContainer bac = p.getBody();
+ AreaContainer footArea = bac.getFootnoteReferenceArea();
+ int basePos = footArea.getCurrentYPosition() - footArea.getHeight();
+ int oldHeight = footArea.getHeight();
+ if(area != null) {
+ footArea.setMaxHeight(area.getMaxHeight() - area.getHeight() + footArea.getHeight());
+ } else {
+ footArea.setMaxHeight(bac.getMaxHeight() + footArea.getHeight());
+ }
+ Status status = fb.layout(footArea);
+ if(status.isIncomplete()) {
+ // add as a pending footnote
+ return false;
+ } else {
+ if(area != null) {
+ area.setMaxHeight(area.getMaxHeight() - footArea.getHeight());
+ }
+ //bac.setMaxHeight(bac.getMaxHeight() - footArea.getHeight() + oldHeight);
+ if(bac.getFootnoteState() == 0) {
+ Area ar = bac.getMainReferenceArea();
+ decreaseMaxHeight(ar, footArea.getHeight() - oldHeight);
+ footArea.setYPosition(basePos + footArea.getHeight());
+ }
+ }
+ } catch(FOPException fope) {
+ return false;
+ }
+ return true;
+ }
+
+ protected static void decreaseMaxHeight(Area ar, int change) {
+ ar.setMaxHeight(ar.getMaxHeight() - change);
+ Vector childs = ar.getChildren();
+ for(Enumeration en = childs.elements(); en.hasMoreElements(); ) {
+ Object obj = en.nextElement();
+ if(obj instanceof Area) {
+ Area childArea = (Area)obj;
+ decreaseMaxHeight(childArea, change);
+ }
+ }
+ }
+}
--- /dev/null
+/*-- $Id$ --
+
+ ============================================================================
+ The Apache Software License, Version 1.1
+ ============================================================================
+
+ Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modifica-
+ tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. The end-user documentation included with the redistribution, if any, must
+ include the following acknowledgment: "This product includes software
+ developed by the Apache Software Foundation (http://www.apache.org/)."
+ Alternately, this acknowledgment may appear in the software itself, if
+ and wherever such third-party acknowledgments normally appear.
+
+ 4. The names "FOP" and "Apache Software Foundation" must not be used to
+ endorse or promote products derived from this software without prior
+ written permission. For written permission, please contact
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation and was originally created by
+ James Tauber <jtauber@jtauber.com>. For more information on the Apache
+ Software Foundation, please see <http://www.apache.org/>.
+
+ */
+
+package org.apache.fop.fo.flow;
+
+// FOP
+import org.apache.fop.fo.*;
+import org.apache.fop.layout.Area;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.properties.*;
+import org.apache.fop.layout.*;
+
+// Java
+import java.util.Enumeration;
+
+public class FootnoteBody extends FObj {
+ FontState fs;
+ int align;
+ int alignLast;
+ int lineHeight;
+ int startIndent;
+ int endIndent;
+ int textIndent;
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new FootnoteBody(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new FootnoteBody.Maker();
+ }
+
+ public FootnoteBody(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:footnote-body";
+ }
+
+ public Status layout(Area area) throws FOPException {
+ if(this.marker == START) {
+ this.marker = 0;
+ }
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ FontState fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+
+ BlockArea blockArea = new BlockArea(fs, area.getAllocationWidth(),
+ area.spaceLeft(), startIndent, endIndent, textIndent,
+ align, alignLast, lineHeight);
+ blockArea.setPage(area.getPage());
+ blockArea.start();
+
+ blockArea.setAbsoluteHeight(area.getAbsoluteHeight());
+ blockArea.setIDReferences(area.getIDReferences());
+
+ blockArea.setTableCellXOffset(area.getTableCellXOffset());
+
+ int numChildren = this.children.size();
+ for ( int i = this.marker; i < numChildren; i++ ) {
+ FONode fo = (FONode) children.elementAt(i);
+ Status status;
+ if ( (status = fo.layout(blockArea)).isIncomplete() ) {
+ this.resetMarker();
+ return status;
+ }
+ }
+ blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+ return new Status(Status.OK);
+ }
+}
{
throw new FOPException("page masters exhausted. Cannot recover.");
}
- return pageMaster.makePage(areaTree);
+ Page p = pageMaster.makePage(areaTree);
+ if(currentPage != null) {
+ Vector foots = currentPage.getPendingFootnotes();
+ p.setPendingFootnotes(foots);
+ }
+ return p;
}
/**
// FOP
import org.apache.fop.render.Renderer;
+import org.apache.fop.fo.flow.*;
+import org.apache.fop.fo.*;
+import org.apache.fop.apps.*;
// Java
import java.util.Vector;
protected String language;
protected String country;
+ protected Vector pendingFootnotes = null;
+
public BlockArea(FontState fontState, int allocationWidth,
int maxHeight, int startIndent, int endIndent,
int textIndent, int align, int alignLastLine, int lineHeight) {
this.increaseHeight(size);
this.addDisplaySpace(this.halfLeading);
}
+ // add pending footnotes
+ if(pendingFootnotes != null) {
+ for(Enumeration e = pendingFootnotes.elements(); e.hasMoreElements(); ) {
+ FootnoteBody fb = (FootnoteBody)e.nextElement();
+ Page page = getPage();
+ if(!Footnote.layoutFootnote(page, fb, this)) {
+ page.addPendingFootnote(fb);
+ }
+ }
+ pendingFootnotes = null;
+ }
}
public int addPageNumberCitation(FontState fontState, float red,
this.hyphenationRemainCharacterCount = hyphenationRemainCharacterCount;
}
+ public void addFootnote(FootnoteBody fb) {
+ if(pendingFootnotes == null) {
+ pendingFootnotes = new Vector();
+ }
+ pendingFootnotes.addElement(fb);
+ }
}
// the start FO in case of rollback
private FObj startFO;
private boolean isNewSpanArea;
-
+
+ // keeps track of footnote state for multiple layouts
+ private int footnoteState = 0;
+
public BodyAreaContainer(FontState fontState, int xPosition, int yPosition,
int allocationWidth, int maxHeight, int position,
int columnCount, int columnGap) {
{
return isNewSpanArea;
}
-
+
public AreaContainer getCurrentColumnArea()
{
Vector spanAreas = this.mainReferenceArea.getChildren();
SpanArea spanArea = (SpanArea)spanAreas.elementAt(spanAreas.size()-1);
return spanArea.getCurrentColumnArea();
}
+
+ public int getFootnoteState()
+ {
+ return footnoteState;
+ }
+
+ public boolean needsFootnoteAdjusting()
+ {
+ footnoteYPosition = footnoteReferenceArea.getYPosition();
+ switch(footnoteState) {
+ case 0:
+ resetHeights();
+ if(footnoteReferenceArea.getHeight() > 0
+ && mainYPosition + mainReferenceArea.getHeight() > footnoteYPosition) {
+ return true;
+ }
+ case 1:
+ break;
+ }
+ return false;
+ }
+
+ public void adjustFootnoteArea()
+ {
+ footnoteState++;
+ if(footnoteState == 1) {
+ mainReferenceArea.setMaxHeight(footnoteReferenceArea.getYPosition() - mainYPosition);
+ footnoteYPosition = footnoteReferenceArea.getYPosition();
+ footnoteReferenceArea.setMaxHeight(footnoteReferenceArea.getHeight());
+
+ Vector childs = footnoteReferenceArea.getChildren();
+ for(Enumeration en = childs.elements(); en.hasMoreElements(); ) {
+ Object obj = en.nextElement();
+ if(obj instanceof Area) {
+ Area childArea = (Area)obj;
+ footnoteReferenceArea.removeChild(childArea);
+ }
+ }
+
+ getPage().setPendingFootnotes(null);
+ }
+ }
+
+ protected static void resetMaxHeight(Area ar, int change) {
+ ar.setMaxHeight(change);
+ Vector childs = ar.getChildren();
+ for(Enumeration en = childs.elements(); en.hasMoreElements(); ) {
+ Object obj = en.nextElement();
+ if(obj instanceof Area) {
+ Area childArea = (Area)obj;
+ resetMaxHeight(childArea, change);
+ }
+ }
+ }
}
// FOP
import org.apache.fop.render.Renderer;
+import org.apache.fop.fo.flow.*;
+import org.apache.fop.fo.*;
+import org.apache.fop.apps.*;
// Java
import java.util.Vector;
private Vector idList = new Vector();
+ private Vector footnotes = null;
+
Page(AreaTree areaTree, int height, int width) {
this.areaTree = areaTree;
this.height = height;
public Vector getIDList(){
return idList;
}
+
+ public Vector getPendingFootnotes() {
+ return footnotes;
+ }
+
+ public void setPendingFootnotes(Vector v) {
+ footnotes = v;
+ if(footnotes != null) {
+ for(Enumeration e = footnotes.elements(); e.hasMoreElements(); ) {
+ FootnoteBody fb = (FootnoteBody)e.nextElement();
+ if(!Footnote.layoutFootnote(this, fb, null)) {
+ // footnotes are too large to fit on empty page
+ }
+ }
+ footnotes = null;
+ }
+ }
+
+ public void addPendingFootnote(FootnoteBody fb) {
+ if(footnotes == null) {
+ footnotes = new Vector();
+ }
+ footnotes.addElement(fb);
+ }
}