]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
adds footnote support
authorKeiron Liddle <keiron@apache.org>
Wed, 10 Jan 2001 23:56:20 +0000 (23:56 +0000)
committerKeiron Liddle <keiron@apache.org>
Wed, 10 Jan 2001 23:56:20 +0000 (23:56 +0000)
this adds footnotes as they appear and adjusts main area accordingly

multi column support still pending

Code changes sponsored by Dresdner Bank, Germany

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193962 13f79535-47bb-0310-9956-ffa450edef68

src/org/apache/fop/fo/StandardElementMapping.java
src/org/apache/fop/fo/flow/Block.java
src/org/apache/fop/fo/flow/Flow.java
src/org/apache/fop/fo/flow/Footnote.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/FootnoteBody.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/PageSequence.java
src/org/apache/fop/layout/BlockArea.java
src/org/apache/fop/layout/BodyAreaContainer.java
src/org/apache/fop/layout/Page.java

index 0aade4fff3d02bd066ff6bd69b2a82a8c0ce93ac..ce5cc4eff98643dd7ed40127e55c8755dd54ab27 100644 (file)
@@ -108,5 +108,7 @@ public class StandardElementMapping implements ElementMapping {
        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());
     }
 }
index 6b261cc73f7ceae7231c863680388b6e7c32c400..b4c10d10929e62a48d542fb2cf9198ab31e4cc28 100644 (file)
@@ -259,7 +259,8 @@ public class Block extends FObjMixed {
                 startIndent += bodyIndent + distanceBetweenStarts;
             }
 
-            area.getIDReferences().createID(id);
+            if(area.getIDReferences() != null)
+                area.getIDReferences().createID(id);
 
             this.marker = 0;
 
@@ -286,6 +287,10 @@ public class Block extends FObjMixed {
                     if (((FOText) fo).willCreateArea()) {
                         fo.setWidows(blockWidows);
                         break;
+                    } else {
+                        children.removeElementAt(i);
+                        numChildren = this.children.size();
+                        i--;
                     }
                 } else {
                     fo.setWidows(blockWidows);
@@ -293,7 +298,7 @@ public class Block extends FObjMixed {
                 }
             }
 
-            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()) {
@@ -315,10 +320,11 @@ public class Block extends FObjMixed {
             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);
@@ -367,6 +373,7 @@ public class Block extends FObjMixed {
                     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());
@@ -382,6 +389,7 @@ public class Block extends FObjMixed {
 
                 //blockArea.end();
                 area.addChild(blockArea);
+                area.setMaxHeight(area.getMaxHeight() - spaceLeft + blockArea.getMaxHeight());
                 area.increaseHeight(blockArea.getHeight());
                 area.setAbsoluteHeight(blockArea.getAbsoluteHeight());
                 anythingLaidOut = true;
index 91b69503bfecd09f9deef40edeeb71e1d3df4168..8b86bfef7cf17dab36d3dc9b064ee3663c238c8d 100644 (file)
@@ -148,9 +148,10 @@ public class Flow extends FObj {
        
                // 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);
@@ -177,6 +178,15 @@ public class Flow extends FObj {
                        }
                        
                        _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;
diff --git a/src/org/apache/fop/fo/flow/Footnote.java b/src/org/apache/fop/fo/flow/Footnote.java
new file mode 100644 (file)
index 0000000..76da2d0
--- /dev/null
@@ -0,0 +1,162 @@
+/*-- $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);
+            }
+        }
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/FootnoteBody.java b/src/org/apache/fop/fo/flow/FootnoteBody.java
new file mode 100644 (file)
index 0000000..91f6eb8
--- /dev/null
@@ -0,0 +1,131 @@
+/*-- $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);
+    }
+}
index 8538ed79967da95838214a834261266a79badca2..060ccc8941874ac66afe0d0982c4265ac35c0ebd 100644 (file)
@@ -354,7 +354,12 @@ public class PageSequence extends FObj
         {
                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;
     }
 
     /**
index 9f65f5bdccaedb4b73b93f1933d558847b26d47b..20e877f9be7acba2c9091350b33757186f6acf75 100644 (file)
@@ -52,6 +52,9 @@ package org.apache.fop.layout;
 
 // 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;
@@ -92,6 +95,8 @@ public class BlockArea extends Area {
     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) {
@@ -122,6 +127,17 @@ public class BlockArea extends Area {
             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,
@@ -369,4 +385,10 @@ public class BlockArea extends Area {
       this.hyphenationRemainCharacterCount = hyphenationRemainCharacterCount;
     }
 
+    public void addFootnote(FootnoteBody fb) {
+        if(pendingFootnotes == null) {
+            pendingFootnotes = new Vector();
+        }
+        pendingFootnotes.addElement(fb);
+    }
 }
index 798724db818cf4e0d35feb374b6b84f072fd13aa..8362e37d227bf110d0b2c933ecc29a7d9add3fb4 100644 (file)
@@ -92,7 +92,10 @@ public class BodyAreaContainer extends Area {
        // 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) {
@@ -374,11 +377,65 @@ public class BodyAreaContainer extends Area {
        {
                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);
+            }
+        }
+    }
 }
index a530944063a45adbda8be956cf92a67aa814fbd7..c58ebe115f556500f5fdbfc4f0d3858fc8e056fc 100644 (file)
@@ -53,6 +53,9 @@ package org.apache.fop.layout;
 
 // 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;
@@ -77,6 +80,8 @@ public class Page {
 
     private Vector idList = new Vector();
 
+    private Vector footnotes = null;
+
     Page(AreaTree areaTree, int height, int width) {
        this.areaTree = areaTree;
        this.height = height;
@@ -171,4 +176,28 @@ public class Page {
     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);
+    }
 }