]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
1.) fo:Instream-Foreign-Object initialization logic moved from AddLMVisitor
authorGlen Mazza <gmazza@apache.org>
Sat, 14 Aug 2004 18:36:21 +0000 (18:36 +0000)
committerGlen Mazza <gmazza@apache.org>
Sat, 14 Aug 2004 18:36:21 +0000 (18:36 +0000)
to flow.InstreamForiegnObject.java, and the layout logic itself moved to
a new layoutmgr.InstreamForeignObjectLM.java.  (Broke with usual nomenclature of adding
~LayoutManager to end, given that newer 1.1 and post-1.1 FO names are
getting even larger.)

2.) validateChildNode() added for fo:inline.

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

src/java/org/apache/fop/fo/FObjMixed.java
src/java/org/apache/fop/fo/flow/Inline.java
src/java/org/apache/fop/fo/flow/InstreamForeignObject.java
src/java/org/apache/fop/layoutmgr/AddLMVisitor.java
src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java [new file with mode: 0644]

index d5d272f6ee596450ae392476395d20d097e0b72d..902bd3457551cb8fce3e195e9c911749b9f96466 100644 (file)
@@ -26,6 +26,7 @@ import org.apache.fop.layoutmgr.InlineStackingLayoutManager;
 /**
  * Base class for representation of mixed content formatting objects
  * and their processing
+ * @todo define what a "mixed content formatting object" is
  */
 public class FObjMixed extends FObj {
     /** TextInfo for this object */
index 4e97670dc298da9b3c280bdddd97a14ee5c20059..5df8b757306f20a3df95d65e0983ffec9069eb41 100644 (file)
@@ -20,34 +20,23 @@ package org.apache.fop.fo.flow;
 
 // XML
 import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
 import org.xml.sax.SAXParseException;
 
 // FOP
-import org.apache.fop.apps.FOPException;
 import org.apache.fop.fo.CharIterator;
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.FObjMixed;
 import org.apache.fop.fo.InlineCharIterator;
-import org.apache.fop.layoutmgr.AddLMVisitor;
-import org.apache.fop.fo.properties.CommonAccessibility;
-import org.apache.fop.fo.properties.CommonAural;
-import org.apache.fop.fo.properties.CommonBackground;
-import org.apache.fop.fo.properties.CommonBorderAndPadding;
-import org.apache.fop.fo.properties.CommonMarginInline;
-import org.apache.fop.fo.properties.CommonRelativePosition;
 
 /**
- * Class modelling the fo:inline object. See Sec. 6.6.7 of the XSL-FO Standard.
+ * Class modelling the fo:inline formatting object.
  */
 public class Inline extends FObjMixed {
 
-    // Textdecoration
-    /** is this text underlined? */
-    protected boolean underlined = false;
-    /** is this text overlined? */
-    protected boolean overlined = false;
-    /** is this text lined through? */
-    protected boolean lineThrough = false;
+    // used for FO validation
+    private boolean blockOrInlineItemFound = false;
+    private boolean canHaveBlockLevelChildren = true;
 
     /**
      * @param parent FONode that is the parent of this object
@@ -62,28 +51,56 @@ public class Inline extends FObjMixed {
     protected void addProperties(Attributes attlist) throws SAXParseException {
         super.addProperties(attlist);
 
-        if (parent.getName().equals("fo:flow")) {
-            throw new SAXParseException("inline formatting objects cannot"
-                                   + " be directly under flow", locator);
-        }
-
-        int textDecoration = this.propertyList.get(PR_TEXT_DECORATION).getEnum();
-
-        if (textDecoration == TextDecoration.UNDERLINE) {
-            this.underlined = true;
-        }
+       /* Check to see if this node can have block-level children.
+        * See validateChildNode() below.
+        */
+       int lvlLeader = findAncestor("fo:leader");
+       int lvlFootnote = findAncestor("fo:footnote");
+       int lvlInCntr = findAncestor("fo:inline-container");
+
+       if (lvlLeader > 0) {
+           if (lvlInCntr < 0 ||
+               (lvlInCntr > 0 && lvlInCntr > lvlLeader)) {
+               canHaveBlockLevelChildren = false;
+           }
+       } else if (lvlFootnote > 0) {
+           if (lvlInCntr < 0 || lvlInCntr > lvlFootnote) {
+               canHaveBlockLevelChildren = false;
+           }
+       }
 
-        if (textDecoration == TextDecoration.OVERLINE) {
-            this.overlined = true;
-        }
+        getFOInputHandler().startInline(this);
+    }
 
-        if (textDecoration == TextDecoration.LINE_THROUGH) {
-            this.lineThrough = true;
+    /**
+     * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
+     * XSL Content Model: marker* (#PCDATA|%inline;|%block;)*
+     * Additionally: " An fo:inline that is a descendant of an fo:leader
+     *  or fo:footnote may not have block-level children, unless it has a
+     *  nearer ancestor that is an fo:inline-container." (paraphrased)
+     */
+    protected void validateChildNode(Locator loc, String nsURI, String localName) 
+        throws SAXParseException {
+        if (nsURI == FO_URI && localName.equals("marker")) {
+            if (blockOrInlineItemFound) {
+               nodesOutOfOrderError(loc, "fo:marker", 
+                    "(#PCDATA|%inline;|%block;)");
+            }
+        } else if (!isBlockOrInlineItem(nsURI, localName)) {
+            invalidChildError(loc, nsURI, localName);
+        } else if (!canHaveBlockLevelChildren && isBlockItem(nsURI, localName)) {
+            String ruleViolated = 
+                " An fo:inline that is a descendant of an fo:leader" +
+                " or fo:footnote may not have block-level children," +
+                " unless it has a nearer ancestor that is an" +
+                " fo:inline-container.";
+            invalidChildError(loc, nsURI, localName, ruleViolated);
+        } else {
+            blockOrInlineItemFound = true;
         }
-        
-        getFOInputHandler().startInline(this);
     }
 
+
     /**
      * @see org.apache.fop.fo.FONode#end
      */
@@ -98,6 +115,9 @@ public class Inline extends FObjMixed {
         return new InlineCharIterator(this, propMgr.getBorderAndPadding());
     }
 
+    /**
+     * @see org.apache.fop.fo.FObj#getName()
+     */
     public String getName() {
         return "fo:inline";
     }
index f11a7ece37f93641d41555efb47af6e66d810f18..5c7264aa4949c639e7c023bda8efd9eb21e066d0 100644 (file)
@@ -18,6 +18,9 @@
 
 package org.apache.fop.fo.flow;
 
+// Java
+import java.util.List;
+
 // XML
 import org.xml.sax.Attributes;
 import org.xml.sax.Locator;
@@ -25,8 +28,7 @@ import org.xml.sax.SAXParseException;
 
 // FOP
 import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.LMVisited;
-import org.apache.fop.layoutmgr.AddLMVisitor;
+import org.apache.fop.layoutmgr.InstreamForeignObjectLM;
 import org.apache.fop.fo.FObj;
 
 /**
@@ -34,7 +36,7 @@ import org.apache.fop.fo.FObj;
  * This is an atomic inline object that contains
  * xml data.
  */
-public class InstreamForeignObject extends FObj implements LMVisited {
+public class InstreamForeignObject extends FObj {
 
     boolean hasNonXSLNamespaceElement = false;
 
@@ -121,14 +123,16 @@ public class InstreamForeignObject extends FObj implements LMVisited {
     }
 
     /**
-     * This is a hook for the AddLMVisitor class to be able to access
-     * this object.
-     * @param aLMV the AddLMVisitor object that can access this object.
+     * @see org.apache.fop.fo.FObj#addLayoutManager(List)
      */
-    public void acceptVisitor(AddLMVisitor aLMV) {
-        aLMV.serveInstreamForeignObject(this);
+    public void addLayoutManager(List list) {
+        InstreamForeignObjectLM lm = new InstreamForeignObjectLM(this);
+        list.add(lm);
     }
 
+    /**
+     * @see org.apache.fop.fo.FObj#getName()
+     */
     public String getName() {
         return "fo:instream-foreign-object";
     }
index 0373fd170fe104b19369042acb255f4742d56162..fd2d684fa2f68eda7d5df6eb82c207f373e0c974 100644 (file)
 
 /* $Id$ */
 
-
 package org.apache.fop.layoutmgr;
 
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
 import java.util.List;
 import java.util.ListIterator;
 
 import org.apache.fop.area.Trait;
 import org.apache.fop.area.inline.FilledArea;
-import org.apache.fop.area.inline.ForeignObject;
 import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.Space;
-import org.apache.fop.area.inline.Viewport;
 import org.apache.fop.area.inline.TextArea;
 import org.apache.fop.datatypes.Length;
 import org.apache.fop.fo.Constants;
-import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.FObj;
-import org.apache.fop.fo.XMLObj;
-import org.apache.fop.fo.flow.Block;
 import org.apache.fop.fo.flow.Inline;
-import org.apache.fop.fo.flow.InstreamForeignObject;
 import org.apache.fop.fo.flow.Leader;
 import org.apache.fop.fo.flow.Wrapper;
 import org.apache.fop.traits.MinOptMax;
@@ -209,164 +200,4 @@ public class AddLMVisitor {
          }
          return leaderArea;
      }
-
-     public void serveInstreamForeignObject(InstreamForeignObject node) {
-         Viewport areaCurrent = getInstreamForeignObjectInlineArea(node);
-         if (areaCurrent != null) {
-             LeafNodeLayoutManager lm = new LeafNodeLayoutManager(node);
-             lm.setCurrentArea(areaCurrent);
-             lm.setAlignment(node.getProperty(Constants.PR_VERTICAL_ALIGN).getEnum());
-             lm.setLead(areaCurrent.getHeight());
-             currentLMList.add(lm);
-         }
-     }
-     /**
-      * Get the inline area created by this element.
-      *
-      * @return the viewport inline area
-      */
-     public Viewport getInstreamForeignObjectInlineArea(InstreamForeignObject node) {
-         if (node.getChildNodes() == null) {
-             return null;
-         }
-
-         if (node.childNodes.size() != 1) {
-             // error
-             return null;
-         }
-         FONode fo = (FONode) node.childNodes.get(0);
-         if (!(fo instanceof XMLObj)) {
-             // error
-             return null;
-         }
-         XMLObj child = (XMLObj)fo;
-
-         // viewport size is determined by block-progression-dimension
-         // and inline-progression-dimension
-
-         // if replaced then use height then ignore block-progression-dimension
-         //int h = this.propertyList.get("height").getLength().mvalue();
-
-         // use specified line-height then ignore dimension in height direction
-         boolean hasLH = false;//propertyList.get("line-height").getSpecifiedValue() != null;
-
-         Length len;
-
-         int bpd = -1;
-         int ipd = -1;
-         boolean bpdauto = false;
-         if (hasLH) {
-             bpd = node.getProperty(Constants.PR_LINE_HEIGHT).getLength().getValue();
-         } else {
-             // this property does not apply when the line-height applies
-             // isn't the block-progression-dimension always in the same
-             // direction as the line height?
-             len = node.getProperty(Constants.PR_BLOCK_PROGRESSION_DIMENSION | Constants.CP_OPTIMUM).getLength();
-             if (!len.isAuto()) {
-                 bpd = len.getValue();
-             } else {
-                 len = node.getProperty(Constants.PR_HEIGHT).getLength();
-                 if (!len.isAuto()) {
-                     bpd = len.getValue();
-                 }
-             }
-         }
-
-         len = node.getProperty(Constants.PR_INLINE_PROGRESSION_DIMENSION | Constants.CP_OPTIMUM).getLength();
-         if (!len.isAuto()) {
-             ipd = len.getValue();
-         } else {
-             len = node.getProperty(Constants.PR_WIDTH).getLength();
-             if (!len.isAuto()) {
-                 ipd = len.getValue();
-             }
-         }
-
-         // if auto then use the intrinsic size of the content scaled
-         // to the content-height and content-width
-         int cwidth = -1;
-         int cheight = -1;
-         len = node.getProperty(Constants.PR_CONTENT_WIDTH).getLength();
-         if (!len.isAuto()) {
-             /*if(len.scaleToFit()) {
-                 if(ipd != -1) {
-                     cwidth = ipd;
-                 }
-             } else {*/
-             cwidth = len.getValue();
-         }
-         len = node.getProperty(Constants.PR_CONTENT_HEIGHT).getLength();
-         if (!len.isAuto()) {
-             /*if(len.scaleToFit()) {
-                 if(bpd != -1) {
-                     cwidth = bpd;
-                 }
-             } else {*/
-             cheight = len.getValue();
-         }
-
-         Point2D csize = new Point2D.Float(cwidth == -1 ? -1 : cwidth / 1000f,
-                                           cheight == -1 ? -1 : cheight / 1000f);
-         Point2D size = child.getDimension(csize);
-         if (size == null) {
-             // error
-             return null;
-         }
-         if (cwidth == -1) {
-             cwidth = (int)size.getX() * 1000;
-         }
-         if (cheight == -1) {
-             cheight = (int)size.getY() * 1000;
-         }
-         int scaling = node.getProperty(Constants.PR_SCALING).getEnum();
-         if (scaling == Constants.Scaling.UNIFORM) {
-             // adjust the larger
-             double rat1 = cwidth / (size.getX() * 1000f);
-             double rat2 = cheight / (size.getY() * 1000f);
-             if (rat1 < rat2) {
-                 // reduce cheight
-                 cheight = (int)(rat1 * size.getY() * 1000);
-             } else {
-                 cwidth = (int)(rat2 * size.getX() * 1000);
-             }
-         }
-
-         if (ipd == -1) {
-             ipd = cwidth;
-         }
-         if (bpd == -1) {
-             bpd = cheight;
-         }
-
-         boolean clip = false;
-         if (cwidth > ipd || cheight > bpd) {
-             int overflow = node.getProperty(Constants.PR_OVERFLOW).getEnum();
-             if (overflow == Constants.Overflow.HIDDEN) {
-                 clip = true;
-             } else if (overflow == Constants.Overflow.ERROR_IF_OVERFLOW) {
-                 node.getLogger().error("Instream foreign object overflows the viewport: clipping");
-                 clip = true;
-             }
-         }
-
-         int xoffset = node.computeXOffset(ipd, cwidth);
-         int yoffset = node.computeYOffset(bpd, cheight);
-
-         Rectangle2D placement = new Rectangle2D.Float(xoffset, yoffset, cwidth, cheight);
-
-         org.w3c.dom.Document doc = child.getDOMDocument();
-         String ns = child.getDocumentNamespace();
-
-         node.childNodes = null;
-         ForeignObject foreign = new ForeignObject(doc, ns);
-
-         Viewport areaCurrent = new Viewport(foreign);
-         areaCurrent.setWidth(ipd);
-         areaCurrent.setHeight(bpd);
-         areaCurrent.setContentPosition(placement);
-         areaCurrent.setClip(clip);
-         areaCurrent.setOffset(0);
-
-         return areaCurrent;
-     }
 }
diff --git a/src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java b/src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java
new file mode 100644 (file)
index 0000000..eb582e3
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.layoutmgr;
+
+// Java
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+// FOP
+import org.apache.fop.datatypes.Length;
+import org.apache.fop.fo.XMLObj;
+import org.apache.fop.fo.flow.InstreamForeignObject;
+import org.apache.fop.area.inline.ForeignObject;
+import org.apache.fop.area.inline.InlineArea;
+import org.apache.fop.area.inline.Viewport;
+
+/**
+ * LayoutManager for the fo:basic-link formatting object
+ */
+public class InstreamForeignObjectLM extends LeafNodeLayoutManager {
+
+    InstreamForeignObject ifoNode;
+    
+    /**
+     * Constructor
+     * @param node the formatting object that creates this area
+     */
+    public InstreamForeignObjectLM(InstreamForeignObject node) {
+        super(node);
+        ifoNode = node;
+        Viewport areaCurrent = getInlineArea();
+        setCurrentArea(areaCurrent);
+        setAlignment(node.getProperty(PR_VERTICAL_ALIGN).getEnum());
+        setLead(areaCurrent.getHeight());
+    }
+
+    /**
+     * Get the inline area created by this element.
+     *
+     * @return the viewport inline area
+     */
+    private Viewport getInlineArea() {
+        XMLObj child = (XMLObj) ifoNode.childNodes.get(0);
+
+        // viewport size is determined by block-progression-dimension
+        // and inline-progression-dimension
+
+        // if replaced then use height then ignore block-progression-dimension
+        //int h = this.propertyList.get("height").getLength().mvalue();
+
+        // use specified line-height then ignore dimension in height direction
+        boolean hasLH = false;//propertyList.get("line-height").getSpecifiedValue() != null;
+
+        Length len;
+
+        int bpd = -1;
+        int ipd = -1;
+        boolean bpdauto = false;
+        if (hasLH) {
+            bpd = ifoNode.getProperty(PR_LINE_HEIGHT).getLength().getValue();
+        } else {
+            // this property does not apply when the line-height applies
+            // isn't the block-progression-dimension always in the same
+            // direction as the line height?
+            len = ifoNode.getProperty(PR_BLOCK_PROGRESSION_DIMENSION | CP_OPTIMUM).getLength();
+            if (!len.isAuto()) {
+                bpd = len.getValue();
+            } else {
+                len = ifoNode.getProperty(PR_HEIGHT).getLength();
+                if (!len.isAuto()) {
+                    bpd = len.getValue();
+                }
+            }
+        }
+
+        len = ifoNode.getProperty(PR_INLINE_PROGRESSION_DIMENSION | CP_OPTIMUM).getLength();
+        if (!len.isAuto()) {
+            ipd = len.getValue();
+        } else {
+            len = ifoNode.getProperty(PR_WIDTH).getLength();
+            if (!len.isAuto()) {
+                ipd = len.getValue();
+            }
+        }
+
+        // if auto then use the intrinsic size of the content scaled
+        // to the content-height and content-width
+        int cwidth = -1;
+        int cheight = -1;
+        len = ifoNode.getProperty(PR_CONTENT_WIDTH).getLength();
+        if (!len.isAuto()) {
+            /*if(len.scaleToFit()) {
+                if(ipd != -1) {
+                    cwidth = ipd;
+                }
+            } else {*/
+            cwidth = len.getValue();
+        }
+        len = ifoNode.getProperty(PR_CONTENT_HEIGHT).getLength();
+        if (!len.isAuto()) {
+            /*if(len.scaleToFit()) {
+                if(bpd != -1) {
+                    cwidth = bpd;
+                }
+            } else {*/
+            cheight = len.getValue();
+        }
+
+        Point2D csize = new Point2D.Float(cwidth == -1 ? -1 : cwidth / 1000f,
+                                          cheight == -1 ? -1 : cheight / 1000f);
+        Point2D size = child.getDimension(csize);
+        if (size == null) {
+            // error
+            return null;
+        }
+        if (cwidth == -1) {
+            cwidth = (int)size.getX() * 1000;
+        }
+        if (cheight == -1) {
+            cheight = (int)size.getY() * 1000;
+        }
+        int scaling = ifoNode.getProperty(PR_SCALING).getEnum();
+        if (scaling == Scaling.UNIFORM) {
+            // adjust the larger
+            double rat1 = cwidth / (size.getX() * 1000f);
+            double rat2 = cheight / (size.getY() * 1000f);
+            if (rat1 < rat2) {
+                // reduce cheight
+                cheight = (int)(rat1 * size.getY() * 1000);
+            } else {
+                cwidth = (int)(rat2 * size.getX() * 1000);
+            }
+        }
+
+        if (ipd == -1) {
+            ipd = cwidth;
+        }
+        if (bpd == -1) {
+            bpd = cheight;
+        }
+
+        boolean clip = false;
+        if (cwidth > ipd || cheight > bpd) {
+            int overflow = ifoNode.getProperty(PR_OVERFLOW).getEnum();
+            if (overflow == Overflow.HIDDEN) {
+                clip = true;
+            } else if (overflow == Overflow.ERROR_IF_OVERFLOW) {
+                ifoNode.getLogger().error("Instream foreign object overflows the viewport: clipping");
+                clip = true;
+            }
+        }
+
+        int xoffset = ifoNode.computeXOffset(ipd, cwidth);
+        int yoffset = ifoNode.computeYOffset(bpd, cheight);
+
+        Rectangle2D placement = new Rectangle2D.Float(xoffset, yoffset, cwidth, cheight);
+
+        org.w3c.dom.Document doc = child.getDOMDocument();
+        String ns = child.getDocumentNamespace();
+
+        ifoNode.childNodes = null;
+        ForeignObject foreign = new ForeignObject(doc, ns);
+
+        Viewport areaCurrent = new Viewport(foreign);
+        areaCurrent.setWidth(ipd);
+        areaCurrent.setHeight(bpd);
+        areaCurrent.setContentPosition(placement);
+        areaCurrent.setClip(clip);
+        areaCurrent.setOffset(0);
+
+        return areaCurrent;
+    }
+}
+