gmazza 2004/08/14 11:36:22 Modified: src/java/org/apache/fop/fo FObjMixed.java src/java/org/apache/fop/fo/flow Inline.java InstreamForeignObject.java src/java/org/apache/fop/layoutmgr AddLMVisitor.java Added: src/java/org/apache/fop/layoutmgr InstreamForeignObjectLM.java Log: 1.) fo:Instream-Foreign-Object initialization logic moved from AddLMVisitor 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. Revision Changes Path 1.33 +1 -0 xml-fop/src/java/org/apache/fop/fo/FObjMixed.java Index: FObjMixed.java =================================================================== RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/FObjMixed.java,v retrieving revision 1.32 retrieving revision 1.33 diff -u -r1.32 -r1.33 --- FObjMixed.java 11 Aug 2004 04:15:25 -0000 1.32 +++ FObjMixed.java 14 Aug 2004 18:36:21 -0000 1.33 @@ -26,6 +26,7 @@ /** * 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 */ 1.25 +53 -33 xml-fop/src/java/org/apache/fop/fo/flow/Inline.java Index: Inline.java =================================================================== RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/flow/Inline.java,v retrieving revision 1.24 retrieving revision 1.25 diff -u -r1.24 -r1.25 --- Inline.java 11 Aug 2004 04:15:25 -0000 1.24 +++ Inline.java 14 Aug 2004 18:36:21 -0000 1.25 @@ -20,34 +20,23 @@ // 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 @@ 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 @@ return new InlineCharIterator(this, propMgr.getBorderAndPadding()); } + /** + * @see org.apache.fop.fo.FObj#getName() + */ public String getName() { return "fo:inline"; } 1.20 +12 -8 xml-fop/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java Index: InstreamForeignObject.java =================================================================== RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- InstreamForeignObject.java 8 Aug 2004 18:39:23 -0000 1.19 +++ InstreamForeignObject.java 14 Aug 2004 18:36:21 -0000 1.20 @@ -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 @@ // 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 @@ * 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 @@ } /** - * 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"; } 1.56 +1 -170 xml-fop/src/java/org/apache/fop/layoutmgr/AddLMVisitor.java Index: AddLMVisitor.java =================================================================== RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/AddLMVisitor.java,v retrieving revision 1.55 retrieving revision 1.56 diff -u -r1.55 -r1.56 --- AddLMVisitor.java 13 Aug 2004 12:29:51 -0000 1.55 +++ AddLMVisitor.java 14 Aug 2004 18:36:21 -0000 1.56 @@ -16,29 +16,20 @@ /* $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; @@ -208,165 +199,5 @@ leaderArea = fa; } 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; } } 1.1 xml-fop/src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java Index: InstreamForeignObjectLM.java =================================================================== /* * 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: InstreamForeignObjectLM.java,v 1.1 2004/08/14 18:36:21 gmazza Exp $ */ 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; } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]