From: Simon Steiner Date: Fri, 13 Jul 2018 10:29:57 +0000 (+0000) Subject: FOP-1760: Add change bar generation X-Git-Tag: fop-2_4~49 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e6748b4ed1522214915b2e3cd4df2db9f2b7b3b2;p=xmlgraphics-fop.git FOP-1760: Add change bar generation git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1835810 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/fop-core/src/main/java/org/apache/fop/area/Area.java b/fop-core/src/main/java/org/apache/fop/area/Area.java index 895367c19..87f645dd2 100644 --- a/fop-core/src/main/java/org/apache/fop/area/Area.java +++ b/fop-core/src/main/java/org/apache/fop/area/Area.java @@ -20,12 +20,14 @@ package org.apache.fop.area; import java.io.Serializable; +import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.fo.flow.ChangeBar; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.WritingModeTraitsGetter; @@ -128,6 +130,29 @@ public class Area extends AreaTreeObject implements Serializable { */ protected static final Log log = LogFactory.getLog(Area.class); + /** + * The active change bar list + */ + private List changeBarList; + + /** + * Returns the active change bar list. + * + * @return The active change bar list + */ + public List getChangeBarList() { + return changeBarList; + } + + /** + * Sets the active change bar list. + * + * @param changeBarList The active change bar list + */ + public void setChangeBarList(List changeBarList) { + this.changeBarList = changeBarList; + } + /** * Get the area class of this area. * diff --git a/fop-core/src/main/java/org/apache/fop/area/AreaTreeParser.java b/fop-core/src/main/java/org/apache/fop/area/AreaTreeParser.java index 41563a85e..587e8e449 100644 --- a/fop-core/src/main/java/org/apache/fop/area/AreaTreeParser.java +++ b/fop-core/src/main/java/org/apache/fop/area/AreaTreeParser.java @@ -66,6 +66,7 @@ import org.apache.fop.area.inline.Container; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.InlineBlock; import org.apache.fop.area.inline.InlineBlockParent; import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.inline.InlineViewport; @@ -80,6 +81,7 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.traits.BorderProps; +import org.apache.fop.traits.Direction; import org.apache.fop.traits.Visibility; import org.apache.fop.util.ColorUtil; import org.apache.fop.util.ContentHandlerFactory; @@ -190,6 +192,7 @@ public class AreaTreeParser { makers.put("block", new BlockMaker()); makers.put("lineArea", new LineAreaMaker()); makers.put("inline", new InlineMaker()); + makers.put("inlineblock", new InlineBlockMaker()); makers.put("inlineparent", new InlineParentMaker()); makers.put("inlineblockparent", new InlineBlockParentMaker()); makers.put("text", new TextMaker()); @@ -594,6 +597,17 @@ public class AreaTreeParser { BodyRegion body = getCurrentBodyRegion(); Span span = new Span(columnCount, body.getColumnGap(), ipd); + + String blockDirection = attributes.getValue("block-progression-direction"); + if (blockDirection != null) { + span.addTrait(Trait.BLOCK_PROGRESSION_DIRECTION, Direction.valueOf(blockDirection)); + } + + String inlineDirection = attributes.getValue("inline-progression-direction"); + if (inlineDirection != null) { + span.addTrait(Trait.INLINE_PROGRESSION_DIRECTION, Direction.valueOf(inlineDirection)); + } + transferForeignObjects(attributes, span); setAreaAttributes(attributes, span); body.getMainReference().getSpans().add(span); @@ -723,6 +737,34 @@ public class AreaTreeParser { } } + private class InlineBlockMaker extends AbstractMaker { + + public void startElement(Attributes attributes) { + + Block block = new Block(); + + if (attributes.getValue("left-offset") != null) { + block.setXOffset(XMLUtil.getAttributeAsInt(attributes, "left-offset", 0)); + } + if (attributes.getValue("top-offset") != null) { + block.setYOffset(XMLUtil.getAttributeAsInt(attributes, "top-offset", 0)); + } + transferForeignObjects(attributes, block); + setAreaAttributes(attributes, block); + setTraits(attributes, block, SUBSET_COMMON); + setTraits(attributes, block, SUBSET_BOX); + setTraits(attributes, block, SUBSET_COLOR); + Area parent = (Area)areaStack.peek(); + InlineBlock inlineBlock = new InlineBlock(block); + parent.addChildArea(inlineBlock); + areaStack.push(inlineBlock); + } + + public void endElement() { + assertObjectOfClass(areaStack.pop(), InlineBlock.class); + } + } + private class InlineParentMaker extends AbstractMaker { public void startElement(Attributes attributes) { diff --git a/fop-core/src/main/java/org/apache/fop/area/Span.java b/fop-core/src/main/java/org/apache/fop/area/Span.java index 41610f355..9fa22c6fd 100644 --- a/fop-core/src/main/java/org/apache/fop/area/Span.java +++ b/fop-core/src/main/java/org/apache/fop/area/Span.java @@ -81,6 +81,15 @@ public class Span extends Area { return colCount; } + /** + * Get the column gap for this span area. + * + * @return the column gap for this span area + */ + public int getColumnGap() { + return colGap; + } + /** * Get the width of a single column within this Span * @@ -206,6 +215,8 @@ public class Span extends Area { } break; } + addTrait(Trait.INLINE_PROGRESSION_DIRECTION, wmtg.getInlineProgressionDirection()); + addTrait(Trait.BLOCK_PROGRESSION_DIRECTION, wmtg.getBlockProgressionDirection()); } /** {@inheritDoc} */ diff --git a/fop-core/src/main/java/org/apache/fop/area/inline/InlineBlock.java b/fop-core/src/main/java/org/apache/fop/area/inline/InlineBlock.java new file mode 100644 index 000000000..9b5f96708 --- /dev/null +++ b/fop-core/src/main/java/org/apache/fop/area/inline/InlineBlock.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.area.inline; + +import org.apache.fop.area.Block; + +/** + * This is the inline block area class. + * It wraps the child block when it has to be placed into inline parent. + */ +public class InlineBlock extends InlineParent { + + private static final long serialVersionUID = -3725062353292109517L; + private final Block block; + + public InlineBlock(Block block) { + this.block = block; + } + + /** + * @return the wrapped block + */ + public Block getBlock() { + return block; + } +} diff --git a/fop-core/src/main/java/org/apache/fop/area/inline/TextArea.java b/fop-core/src/main/java/org/apache/fop/area/inline/TextArea.java index 3081a38eb..a03e536ce 100644 --- a/fop-core/src/main/java/org/apache/fop/area/inline/TextArea.java +++ b/fop-core/src/main/java/org/apache/fop/area/inline/TextArea.java @@ -95,6 +95,7 @@ public class TextArea extends AbstractTextArea { WordArea wordArea = new WordArea( blockProgressionOffset, minWordLevel, word, letterAdjust, levels, gposAdjustments); wordArea.setIPD(ipd); + wordArea.setChangeBarList(getChangeBarList()); addChildArea(wordArea); wordArea.setParentArea(this); updateLevel(minWordLevel); @@ -113,6 +114,7 @@ public class TextArea extends AbstractTextArea { char space, int ipd, boolean adjustable, int blockProgressionOffset, int level) { SpaceArea spaceArea = new SpaceArea(blockProgressionOffset, level, space, adjustable); spaceArea.setIPD(ipd); + spaceArea.setChangeBarList(getChangeBarList()); addChildArea(spaceArea); spaceArea.setParentArea(this); updateLevel(level); diff --git a/fop-core/src/main/java/org/apache/fop/fo/FOElementMapping.java b/fop-core/src/main/java/org/apache/fop/fo/FOElementMapping.java index b087e1d9c..8bf92c2b3 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/FOElementMapping.java +++ b/fop-core/src/main/java/org/apache/fop/fo/FOElementMapping.java @@ -141,6 +141,10 @@ public class FOElementMapping extends ElementMapping { foObjs.put("marker", new MarkerMaker()); foObjs.put("retrieve-marker", new RetrieveMarkerMaker()); foObjs.put("retrieve-table-marker", new RetrieveTableMarkerMaker()); + + // change bars + foObjs.put("change-bar-begin", new ChangeBarBeginMaker()); + foObjs.put("change-bar-end", new ChangeBarEndMaker()); } } @@ -527,4 +531,16 @@ public class FOElementMapping extends ElementMapping { return new org.apache.fop.fo.flow.RetrieveTableMarker(parent); } } + + static class ChangeBarBeginMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new org.apache.fop.fo.flow.ChangeBarBegin(parent); + } + } + + static class ChangeBarEndMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new org.apache.fop.fo.flow.ChangeBarEnd(parent); + } + } } diff --git a/fop-core/src/main/java/org/apache/fop/fo/FONode.java b/fop-core/src/main/java/org/apache/fop/fo/FONode.java index b4e0ec0fe..f3c582dd5 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/FONode.java +++ b/fop-core/src/main/java/org/apache/fop/fo/FONode.java @@ -20,6 +20,7 @@ package org.apache.fop.fo; // Java +import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Stack; @@ -42,6 +43,7 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.extensions.InternalElementMapping; import org.apache.fop.fo.extensions.svg.SVGElementMapping; +import org.apache.fop.fo.flow.ChangeBar; import org.apache.fop.fo.pagination.Root; import org.apache.fop.util.CharUtilities; import org.apache.fop.util.ContentHandlerFactory; @@ -63,6 +65,12 @@ public abstract class FONode implements Cloneable { /** pointer to the sibling nodes */ protected FONode[] siblings; + /** The list of active change bars for the given node */ + protected List nodeChangeBarList; + + /** The list of active change bars for the start of the given node */ + protected List startOfNodeChangeBarList; + /** * Marks the location of this object from the input FO *
Call locator.getSystemId(), @@ -173,6 +181,18 @@ public abstract class FONode implements Cloneable { return getBuilderContext().inMarker(); } + /** + * Tests if the given element is a change bar element. + * + * @param namespaceURI The name space of the element + * @param localName The local name of the element + * @return A boolean value true if the given element is a change bar element + */ + public boolean isChangeBarElement(String namespaceURI, String localName) { + return FO_URI.equals(namespaceURI) + && (localName.equals("change-bar-begin") || localName.equals("change-bar-end")); + } + /** * Returns the user agent that is associated with the * tree's FOEventHandler. @@ -1082,6 +1102,15 @@ public abstract class FONode implements Cloneable { } + /** + * Returns the list of active change bars. + * + * @return The list of active change bars + */ + public List getChangeBarList() { + return nodeChangeBarList; + } + /** * Sets the structure tree element. * diff --git a/fop-core/src/main/java/org/apache/fop/fo/FOPropertyMapping.java b/fop-core/src/main/java/org/apache/fop/fo/FOPropertyMapping.java index da92cc834..0b8da47cc 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/fop-core/src/main/java/org/apache/fop/fo/FOPropertyMapping.java @@ -322,6 +322,7 @@ public final class FOPropertyMapping implements Constants { gp.createTableProperties(); gp.createWritingModeProperties(); gp.createMiscProperties(); + gp.createChangeBarProperties(); // Hardcode the subproperties. addSubpropMakerName("length", CP_LENGTH); @@ -2588,6 +2589,56 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("writing-mode", m); } + private void createChangeBarProperties() { + PropertyMaker m; + + // change-bar-class + m = new StringProperty.Maker(PR_CHANGE_BAR_CLASS); + m.setInherited(false); + m.setDefault(""); + addPropertyMaker("change-bar-class", m); + + // change-bar-color + m = new ColorProperty.Maker(PR_CHANGE_BAR_COLOR); + + m.setInherited(true); + // TODO: fall back to "color" property + m.setDefault("black"); + addPropertyMaker("change-bar-color", m); + + // change-bar-placement + m = new EnumProperty.Maker(PR_CHANGE_BAR_PLACEMENT); + m.setInherited(true); + m.setDefault("start"); + m.addEnum("start", getEnumProperty(EN_START, "START")); + m.addEnum("end", getEnumProperty(EN_END, "END")); + m.addEnum("left", getEnumProperty(EN_LEFT, "LEFT")); + m.addEnum("right", getEnumProperty(EN_RIGHT, "RIGHT")); + m.addEnum("inside", getEnumProperty(EN_INSIDE, "INSIDE")); + m.addEnum("outside", getEnumProperty(EN_OUTSIDE, "OUTSIDE")); + m.addEnum("alternate", getEnumProperty(EN_ALTERNATE, "ALTERNATE")); + addPropertyMaker("change-bar-placement", m); + + // change-bar-style + m = new EnumProperty.Maker(PR_CHANGE_BAR_STYLE); + m.useGeneric(genericBorderStyle); + m.setInherited(true); + m.setDefault("solid"); + addPropertyMaker("change-bar-style", m); + + // change-bar-width + m = new LengthProperty.Maker(PR_CHANGE_BAR_WIDTH); + m.setInherited(true); + m.setDefault("6pt"); + addPropertyMaker("change-bar-width", m); + + // change-bar-offset + m = new LengthProperty.Maker(PR_CHANGE_BAR_OFFSET); + m.setInherited(true); + m.setDefault("6pt"); + addPropertyMaker("change-bar-offset", m); + } + private void createMiscProperties() { PropertyMaker m; diff --git a/fop-core/src/main/java/org/apache/fop/fo/FOText.java b/fop-core/src/main/java/org/apache/fop/fo/FOText.java index 563d96993..207c3184c 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/FOText.java +++ b/fop-core/src/main/java/org/apache/fop/fo/FOText.java @@ -33,6 +33,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.flow.Block; +import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.properties.CommonFont; import org.apache.fop.fo.properties.CommonHyphenation; import org.apache.fop.fo.properties.CommonTextDecoration; @@ -109,6 +110,11 @@ public class FOText extends FONode implements CharSequence, TextFragment { */ public FOText(FONode parent) { super(parent); + + PageSequence pageSequence = getRoot().getLastPageSequence(); + if (pageSequence != null && pageSequence.hasChangeBars()) { + nodeChangeBarList = getRoot().getLastPageSequence().getClonedChangeBarList(); + } } /** {@inheritDoc} */ diff --git a/fop-core/src/main/java/org/apache/fop/fo/FOTreeBuilder.java b/fop-core/src/main/java/org/apache/fop/fo/FOTreeBuilder.java index e3afbbb75..249f0e0fe 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/fop-core/src/main/java/org/apache/fop/fo/FOTreeBuilder.java @@ -273,7 +273,9 @@ public class FOTreeBuilder extends DefaultHandler { if (currentFObj.getNamespaceURI().equals(FOElementMapping.URI) || currentFObj.getNamespaceURI().equals(ExtensionElementMapping.URI) || currentFObj.getNamespaceURI().equals(PDFElementMapping.NAMESPACE)) { - currentFObj.validateChildNode(locator, namespaceURI, localName); + if (!currentFObj.isChangeBarElement(namespaceURI, localName)) { + currentFObj.validateChildNode(locator, namespaceURI, localName); + } } } diff --git a/fop-core/src/main/java/org/apache/fop/fo/FOValidationEventProducer.java b/fop-core/src/main/java/org/apache/fop/fo/FOValidationEventProducer.java index a96cb3fe3..452a9f563 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/FOValidationEventProducer.java +++ b/fop-core/src/main/java/org/apache/fop/fo/FOValidationEventProducer.java @@ -381,6 +381,47 @@ public interface FOValidationEventProducer extends EventProducer { void unknownFormattingObject(Object source, String elementName, QName offendingNode, Locator loc); + /** + * A class for change bars is not unique. + * @param source the event source + * @param elementName the name of the context node + * @param name the class name + * @param loc the location of the error or null + * @event.severity FATAL + */ + void changeBarClassNotUnique(Object source, String elementName, String name, + Locator loc); + + /** + * Change bars were not stacked correctly + * @param source the event source + * @param elementName the name of the context node + * @param beginName the class name of the beginning change bar + * @param endName the class name of the ending change bar + * @param loc the location of the error or null + * @event.severity FATAL + */ + void changeBarWrongStacking(Object source, String elementName, String beginName, + String endName, Locator loc); + + /** + * Change bar ended without a start of bar occurred + * @param source the event source + * @param elementName the name of the context node + * @param loc the location of the error or null + * @event.severity FATAL + */ + void changeBarNoBegin(Object source, String elementName, Locator loc); + + /** + * Change bar not descendant of fo:flow or fo:static-content + * @param source the event source + * @param elementName the name of the context node + * @param loc the location of the error or null + * @event.severity FATAL + */ + void changeBarWrongAncestor(Object source, String elementName, Locator loc); + /** * Alternate text is missing for a graphic element. * diff --git a/fop-core/src/main/java/org/apache/fop/fo/FObj.java b/fop-core/src/main/java/org/apache/fop/fo/FObj.java index fc105e7e6..f57e59bd1 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/FObj.java +++ b/fop-core/src/main/java/org/apache/fop/fo/FObj.java @@ -21,6 +21,7 @@ package org.apache.fop.fo; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -34,7 +35,9 @@ import org.apache.xmlgraphics.util.QName; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.fo.flow.ChangeBar; import org.apache.fop.fo.flow.Marker; +import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.PropertyMaker; @@ -182,6 +185,39 @@ public abstract class FObj extends FONode implements Constants { if (id != null) { checkId(id); } + + PageSequence pageSequence = getRoot().getLastPageSequence(); + if (pageSequence != null && pageSequence.hasChangeBars()) { + startOfNodeChangeBarList = pageSequence.getClonedChangeBarList(); + } + } + + /** + * {@inheritDoc} + * @throws FOPException FOP Exception + */ + public void endOfNode() throws FOPException { + + List endOfNodeChangeBarList = null; + + PageSequence pageSequence = getRoot().getLastPageSequence(); + if (pageSequence != null) { + endOfNodeChangeBarList = pageSequence.getClonedChangeBarList(); + } + + if (startOfNodeChangeBarList != null && endOfNodeChangeBarList != null) { + + nodeChangeBarList = new LinkedList(endOfNodeChangeBarList); + nodeChangeBarList.retainAll(startOfNodeChangeBarList); + + if (nodeChangeBarList.isEmpty()) { + nodeChangeBarList = null; + } + + startOfNodeChangeBarList = null; + } + + super.endOfNode(); } /** @@ -492,6 +528,8 @@ public abstract class FObj extends FONode implements Constants { protected boolean isInlineItem(String nsURI, String lName) { return (FO_URI.equals(nsURI) && ("bidi-override".equals(lName) + || "change-bar-begin".equals(lName) + || "change-bar-end".equals(lName) || "character".equals(lName) || "external-graphic".equals(lName) || "instream-foreign-object".equals(lName) diff --git a/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBar.java b/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBar.java new file mode 100644 index 000000000..5fa12346b --- /dev/null +++ b/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBar.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.fo.flow; + +import java.awt.Color; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.datatypes.Length; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.StaticPropertyList; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.properties.SpaceProperty; + +/** + * Common change bar base class. Handles change bar properties and validates child nodes. + */ +public abstract class ChangeBar extends FObj { + + /** + * Constructs a ChangeBar element with common parts for both begin and end change bars. + * + * @param parent The parent node + */ + public ChangeBar(FONode parent) { + super(parent); + } + + /** + * The change bar class (required). + */ + protected String changeBarClass; + + /** + * The change bar color. + */ + protected Color color; + + /** + * The change bar offset. + */ + protected Length offset; + + /** + * The change bar placement. + */ + protected int placement = -1; + + /** + * The change bar style. + */ + protected int style = -1; + + /** + * The change bar width. + */ + protected Length width; + + /** + * The actual line height. + */ + protected SpaceProperty lineHeight; + + /** {@inheritDoc} */ + public void bind(PropertyList pList) throws FOPException { + super.bind(pList); + + changeBarClass = pList.get(PR_CHANGE_BAR_CLASS).getString(); + color = pList.get(PR_CHANGE_BAR_COLOR).getColor(getUserAgent()); + offset = pList.get(PR_CHANGE_BAR_OFFSET).getLength(); + placement = pList.get(PR_CHANGE_BAR_PLACEMENT).getEnum(); + style = pList.get(PR_CHANGE_BAR_STYLE).getEnum(); + width = pList.get(PR_CHANGE_BAR_WIDTH).getLength(); + lineHeight = pList.get(PR_LINE_HEIGHT).getSpace(); + } + + /** {@inheritDoc} */ + protected void validateChildNode( + Locator loc, + String namespaceURI, + String localName) throws ValidationException { + // no children allowed + invalidChildError(loc, namespaceURI, localName); + } + + /** {@inheritDoc} */ + public void processNode(String elementName, Locator locator, + Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); + + if (inMarker()) { + PropertyList newPList = new StaticPropertyList(this, null); + newPList.addAttributesToList(attlist); + bind(newPList); + } + + if (changeBarClass == null || changeBarClass.isEmpty()) { + missingPropertyError("change-bar-class"); + } + + if (findAncestor(FO_FLOW) == -1 + && findAncestor(FO_STATIC_CONTENT) == -1) { + getFOValidationEventProducer().changeBarWrongAncestor(this, getName(), locator); + } + } + + /** + * Adds the current change bar to the active change bar list. + */ + protected void push() { + getRoot().getLastPageSequence().pushChangeBar(this); + } + + /** + * Removes the starting counterpart of the current change bar from the active change bar list. + */ + protected void pop() { + getRoot().getLastPageSequence().popChangeBar(this); + } + + /** + * Returns the starting counterpart of the current (ending) change bar. + * + * @return The starting counterpart of the current (ending) change bar + */ + protected ChangeBar getChangeBarBegin() { + return getRoot().getLastPageSequence().getChangeBarBegin(this); + } + + /** + * Returns the change bar class. + * + * @return The change bar class + */ + public String getChangeBarClass() { + return changeBarClass; + } + + /** + * Returns the change bar color. + * + * @return The change bar color + */ + public Color getColor() { + return color; + } + + /** + * Returns the change bar offset. + * + * @return The change bar offset + */ + public Length getOffset() { + return offset; + } + + /** + * Returns the change bar placement. + * + * @return The change bar placement + */ + public int getPlacement() { + return placement; + } + + /** + * Returns the change bar style. + * + * @return The change bar style + */ + public int getStyle() { + return style; + } + + /** + * Returns the change bar width. + * + * @return The change bar width + */ + public Length getWidth() { + return width; + } + + /** + * Returns the line height. + * + * @return The line height + */ + public SpaceProperty getLineHeight() { + return lineHeight; + } + +} diff --git a/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBarBegin.java b/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBarBegin.java new file mode 100644 index 000000000..961a0e37f --- /dev/null +++ b/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBarBegin.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.fo.flow; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; + +public class ChangeBarBegin extends ChangeBar { + + /** + * Constructs a new ChangeBarBegin element. + * + * @param parent The parent node + */ + public ChangeBarBegin(FONode parent) { + super(parent); + } + + /** {@inheritDoc} */ + public String getLocalName() { + return "change-bar-begin"; + } + + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_CHANGE_BAR_BEGIN} + */ + public int getNameId() { + return FO_CHANGE_BAR_BEGIN; + } + + /** {@inheritDoc} */ + public void processNode(String elementName, Locator locator, + Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); + + push(); + } +} diff --git a/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBarEnd.java b/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBarEnd.java new file mode 100644 index 000000000..4feca13a6 --- /dev/null +++ b/fop-core/src/main/java/org/apache/fop/fo/flow/ChangeBarEnd.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.fo.flow; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; + +public class ChangeBarEnd extends ChangeBar { + + /** + * Constructs a new ChangeBarEnd element. + * + * @param parent The parent node + */ + public ChangeBarEnd(FONode parent) { + super(parent); + } + + /** {@inheritDoc} */ + public String getLocalName() { + return "change-bar-end"; + } + + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_CHANGE_BAR_END} + */ + public int getNameId() { + return FO_CHANGE_BAR_END; + } + + /** {@inheritDoc} */ + public void processNode(String elementName, Locator locator, + Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); + + // check if we have an element on the stack at all + ChangeBar changeBarStart = getChangeBarBegin(); + + if (changeBarStart == null) { + getFOValidationEventProducer().changeBarNoBegin(this, getName(), locator); + } else { + pop(); + } + } +} diff --git a/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableRow.java b/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableRow.java index 2beaf2f99..024b77905 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableRow.java +++ b/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableRow.java @@ -90,9 +90,11 @@ public class TableRow extends TableCellContainer implements BreakPropertySet { /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { if (!inMarker()) { - TableCell cell = (TableCell) child; - TablePart part = (TablePart) getParent(); - addTableCellChild(cell, part.isFirst(this)); + if (child instanceof TableCell) { + TableCell cell = (TableCell) child; + TablePart part = (TablePart) getParent(); + addTableCellChild(cell, part.isFirst(this)); + } } super.addChildNode(child); } diff --git a/fop-core/src/main/java/org/apache/fop/fo/pagination/PageSequence.java b/fop-core/src/main/java/org/apache/fop/fo/pagination/PageSequence.java index a1a966e90..3f82e6822 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/pagination/PageSequence.java +++ b/fop-core/src/main/java/org/apache/fop/fo/pagination/PageSequence.java @@ -19,6 +19,8 @@ package org.apache.fop.fo.pagination; +import java.util.LinkedList; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Stack; @@ -31,6 +33,7 @@ import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.flow.ChangeBar; import org.apache.fop.fo.properties.CommonHyphenation; import org.apache.fop.traits.Direction; import org.apache.fop.traits.WritingMode; @@ -77,6 +80,11 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra */ private Flow mainFlow; + /** + * Active change bars + */ + private final List changeBarList = new LinkedList(); + /** * Create a PageSequence instance that is a child of the * given {@link FONode}. @@ -118,6 +126,7 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra masterReference, getLocator()); } } + getRoot().addPageSequence(this); getFOEventHandler().startPageSequence(this); } @@ -464,4 +473,73 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra return pageSequenceMaster.getLastSimplePageMaster(isOddPage, isFirstPage, isBlank, getMainFlow() .getFlowName()); } + + /** + * Adds the specified change bar to the active change bar list. + * + * @param changeBarBegin The starting change bar element + */ + public void pushChangeBar(ChangeBar changeBarBegin) { + changeBarList.add(changeBarBegin); + } + + /** + * Removes the couple of the specified change bar from the active change bar list. + * + * @param changeBarEnd The ending change bar element + */ + public void popChangeBar(ChangeBar changeBarEnd) { + ChangeBar changeBarBegin = getChangeBarBegin(changeBarEnd); + if (changeBarBegin != null) { + changeBarList.remove(changeBarBegin); + } + } + + /** + * Returns the starting counterpart of the specified ending change bar. + * + * @param changeBarEnd The ending change bar element + * @return The starting counterpart of the specified ending change bar + */ + public ChangeBar getChangeBarBegin(ChangeBar changeBarEnd) { + if (changeBarList.isEmpty()) { + return null; + } else { + String changeBarClass = changeBarEnd.getChangeBarClass(); + for (int i = changeBarList.size() - 1; i >= 0; i--) { + ChangeBar changeBar = changeBarList.get(i); + if (changeBar.getChangeBarClass().equals(changeBarClass)) { + return changeBar; + } + } + } + return null; + } + + /** + * Tests if there are any active change bars. + * + * @return A boolean value true if there are any active change bars + */ + public boolean hasChangeBars() { + return !changeBarList.isEmpty(); + } + + /** + * Returns the list of active change bars. + * + * @return The list of active change bars + */ + public List getChangeBarList() { + return changeBarList; + } + + /** + * Returns the copy of active change bars list. + * + * @return The list containing a copy of the active change bars + */ + public List getClonedChangeBarList() { + return new LinkedList(changeBarList); + } } diff --git a/fop-core/src/main/java/org/apache/fop/fo/pagination/Root.java b/fop-core/src/main/java/org/apache/fop/fo/pagination/Root.java index 51309a65d..3b895b372 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/pagination/Root.java +++ b/fop-core/src/main/java/org/apache/fop/fo/pagination/Root.java @@ -281,6 +281,28 @@ public class Root extends FObj implements CommonAccessibilityHolder { } } + /** + * Adds the specified page sequence. + * + * @param pageSequence The page sequence to add + */ + public void addPageSequence(PageSequence pageSequence) { + pageSequences.add(pageSequence); + } + + /** + * Returns the last page sequence (current while parsing). + * + * @return The last page sequence or null + */ + public PageSequence getLastPageSequence() { + if (getPageSequenceCount() > 0) { + return pageSequences.get(getPageSequenceCount() - 1); + } else { + return null; + } + } + /** * Returns the associated LayoutMasterSet. * @return the LayoutMasterSet instance diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java index b687689bc..ca5d1c507 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java @@ -28,6 +28,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.flow.ChangeBar; /** * The base class for nearly all LayoutManagers. @@ -257,6 +258,19 @@ public abstract class AbstractBaseLayoutManager return fobj; } + /** + * Returns the active change bar list. + * + * @return The active change bar list + */ + public List getChangeBarList() { + if (fobj == null) { + return null; + } else { + return fobj.getChangeBarList(); + } + } + /** {@inheritDoc} */ public void reset() { throw new UnsupportedOperationException("Not implemented"); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 9ce113d11..f0fc77577 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -854,6 +854,7 @@ public class BlockContainerLayoutManager extends SpacedBorderedPaddedBlockLayout int level = getBlockContainerFO().getBidiLevel(); viewportBlockArea = new BlockViewport(allowBPDUpdate); + viewportBlockArea.setChangeBarList(getChangeBarList()); viewportBlockArea.addTrait(Trait.IS_VIEWPORT_AREA, Boolean.TRUE); if (level >= 0) { viewportBlockArea.setBidiLevel(level); @@ -892,6 +893,7 @@ public class BlockContainerLayoutManager extends SpacedBorderedPaddedBlockLayout } referenceArea = new Block(); + referenceArea.setChangeBarList(getChangeBarList()); referenceArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); if (level >= 0) { referenceArea.setBidiLevel(level); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 722a011ae..ac0da5f6a 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -357,6 +357,7 @@ public class BlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManager public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); + curBlockArea.setChangeBarList(getChangeBarList()); curBlockArea.setIPD(super.getContentAreaIPD()); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index b8714a570..6069dbcc3 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -124,6 +124,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager int sp = TraitSetter.getEffectiveSpace(adjust, minoptmax); if (sp != 0) { Block spacer = new Block(); + spacer.setChangeBarList(getChangeBarList()); spacer.setBPD(sp); parentLayoutManager.addChildArea(spacer); } diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java index aae5a6b30..06ad4eeba 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java @@ -178,6 +178,7 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan Dimension imageSize = this.imageLayout.getViewportSize(); Block blockArea = new Block(); + blockArea.setChangeBarList(getChangeBarList()); blockArea.setIPD(imageSize.width); LineArea lineArea = new LineArea(); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java index e95cd18ec..3a706a325 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java @@ -39,6 +39,8 @@ import org.apache.fop.fo.flow.BasicLink; import org.apache.fop.fo.flow.BidiOverride; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.BlockContainer; +import org.apache.fop.fo.flow.ChangeBarBegin; +import org.apache.fop.fo.flow.ChangeBarEnd; import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.flow.ExternalGraphic; import org.apache.fop.fo.flow.Float; @@ -146,6 +148,8 @@ public class LayoutManagerMapping implements LayoutManagerMaker { registerMaker(TableHeader.class, new Maker()); registerMaker(Wrapper.class, new WrapperLayoutManagerMaker()); registerMaker(Title.class, new InlineLayoutManagerMaker()); + registerMaker(ChangeBarBegin.class, new Maker()); + registerMaker(ChangeBarEnd.class, new Maker()); registerMaker(MultiCase.class, new MultiCaseLayoutManagerMaker()); registerMaker(MultiSwitch.class, new MultiSwitchLayoutManagerMaker()); registerMaker(Float.class, new FloatLayoutManagerMaker()); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java index 2e1b7f2ae..c06ec522a 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java @@ -133,6 +133,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa getPSLM().addUnresolvedArea(citation.getRefId(), unresolved); text = unresolved; } + text.setChangeBarList(getChangeBarList()); setTraits(text); return text; } diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index c959ee7be..3f68df0e2 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -75,6 +75,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { private TextArea createCharacterArea() { Character fobj = (Character) this.fobj; TextArea text = new TextArea(); + text.setChangeBarList(getChangeBarList()); char ch = fobj.getCharacter(); int ipd = font.getCharWidth(ch); int blockProgressionOffset = 0; diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index af1664981..a5f128f85 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -84,6 +84,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager // get breaks then add areas to title this.parentLM = pslm; holder = new LineArea(); + holder.setChangeBarList(getChangeBarList()); // setUserAgent(foTitle.getUserAgent()); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java index 2719d5c96..8a204607e 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java @@ -42,7 +42,9 @@ public class ExternalGraphicLayoutManager extends AbstractGraphicsLayoutManager /** {@inheritDoc} */ protected Area getChildArea() { - return new Image(((ExternalGraphic) fobj).getSrc()); + Image im = new Image(((ExternalGraphic) fobj).getSrc()); + im.setChangeBarList(getChangeBarList()); + return im; } } diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index df37b9902..85f545e5e 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -206,9 +206,11 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { InlineArea area; if (isInline) { area = createInlineParent(); + area.setChangeBarList(getChangeBarList()); area.setBlockProgressionOffset(0); } else { area = new InlineBlockParent(); + area.setChangeBarList(getChangeBarList()); } if (fobj instanceof Inline || fobj instanceof BasicLink) { TraitSetter.setProducerID(area, fobj.getId()); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index 5b9efa43e..7a8ac8627 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -181,6 +181,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager if (iAdjust != 0) { //getLogger().debug("Add leading space: " + iAdjust); Space ls = new Space(); + ls.setChangeBarList(getChangeBarList()); ls.setIPD(iAdjust); int level = parentArea.getBidiLevel(); if (level >= 0) { diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java index 4a54f582d..6936e3e94 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java @@ -46,7 +46,9 @@ public class InstreamForeignObjectLM extends AbstractGraphicsLayoutManager { org.w3c.dom.Document doc = child.getDOMDocument(); String ns = child.getNamespaceURI(); - return new ForeignObject(doc, ns); + ForeignObject obj = new ForeignObject(doc, ns); + obj.setChangeBarList(getChangeBarList()); + return obj; } } diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index 5f65a5969..a6d695b06 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -217,6 +217,10 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { leaderArea.setBidiLevel(fobj.getBidiLevelRecursive()); } } + + assert leaderArea != null; + leaderArea.setChangeBarList(getChangeBarList()); + TraitSetter.setProducerID(leaderArea, fobj.getId()); return leaderArea; } diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 8ee5d1e70..c15c1d0be 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -1504,6 +1504,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager LineArea lineArea = new LineArea( (lbp.getLeafPos() < seq.size() - 1 ? textAlignment : textAlignmentLast), lbp.difference, lbp.availableStretch, lbp.availableShrink); + lineArea.setChangeBarList(getChangeBarList()); + if (lbp.startIndent != 0) { lineArea.addTrait(Trait.START_INDENT, lbp.startIndent); } @@ -1619,6 +1621,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } LineArea lineArea = new LineArea(); + lineArea.setChangeBarList(getChangeBarList()); setCurrentArea(lineArea); LayoutContext lc = LayoutContext.newInstance(); lc.setAlignmentContext(alignmentContext); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 27bd544dd..3134ebb17 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -32,6 +32,7 @@ import org.apache.fop.area.Trait; import org.apache.fop.area.inline.TextArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOText; +import org.apache.fop.fo.flow.ChangeBar; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontSelector; import org.apache.fop.fonts.GlyphMapping; @@ -312,6 +313,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { TextArea textArea = new TextAreaBuilder(realWidth, totalAdjust, context, firstMappingIndex, lastMappingIndex, context.isLastArea(), mapping.font).build(); + textArea.setChangeBarList(getChangeBarList()); // wordSpaceDim is computed in relation to wordSpaceIPD.opt // but the renderer needs to know the adjustment in relation @@ -411,6 +413,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { textArea = new TextArea(width.getStretch(), width.getShrink(), adjust); } + textArea.setChangeBarList(getChangeBarList()); } private void setInlineProgressionDimension() { @@ -1457,6 +1460,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } + @Override + public List getChangeBarList() { + if (foText == null) { + return null; + } else { + return foText.getChangeBarList(); + } + } + /** {@inheritDoc} */ public String toString() { return super.toString() + "{" diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index 9b37e2405..ff2c59f4a 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -68,10 +68,12 @@ public class WrapperLayoutManager extends LeafNodeLayoutManager { if (parentLayoutManager instanceof BlockStackingLayoutManager && !(parentLayoutManager instanceof BlockLayoutManager)) { Block helperBlock = new Block(); + helperBlock.setChangeBarList(getChangeBarList()); TraitSetter.setProducerID(helperBlock, fobj.getId()); parentLayoutManager.addChildArea(helperBlock); } else { InlineArea area = getEffectiveArea(context); + area.setChangeBarList(getChangeBarList()); parentLayoutManager.addChildArea(area); } } diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index d39b63477..b73abeb0d 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -216,6 +216,7 @@ public class ListBlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManag public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); + curBlockArea.setChangeBarList(getChangeBarList()); // Set up dimensions // Must get dimensions from parent area diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 214ba6269..0cc877e37 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -176,6 +176,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager imp public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); + curBlockArea.setChangeBarList(getChangeBarList()); curBlockArea.setPositioning(Block.ABSOLUTE); // set position curBlockArea.setXOffset(xOffset); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 9d9769a7c..764575ac8 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -739,6 +739,7 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); + curBlockArea.setChangeBarList(getChangeBarList()); // Set up dimensions /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/RowPainter.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/RowPainter.java index cbc19c1ec..06dda5efe 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -468,6 +468,7 @@ class RowPainter { //generate the block area Block block = new Block(); + block.setChangeBarList(tclm.getTableLM().getFObj().getChangeBarList()); block.setPositioning(Block.ABSOLUTE); block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); block.setIPD(ipd); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index aaa896ce3..d95e508c5 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -179,6 +179,8 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); + curBlockArea.setChangeBarList(getChangeBarList()); + // Set up dimensions // Must get dimensions from parent area Area parentArea = parentLayoutManager.getParentArea(curBlockArea); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 8823c0fae..ee4cba2e4 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -175,6 +175,8 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); + curBlockArea.setChangeBarList(getChangeBarList()); + // Set up dimensions // Must get dimensions from parent area Area parentArea = parentLayoutManager.getParentArea(curBlockArea); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index cfa064db6..a56b00ce7 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -529,11 +529,13 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager { if (usedBPD < cellBPD) { if (getTableCell().getDisplayAlign() == EN_CENTER) { Block space = new Block(); + space.setChangeBarList(getChangeBarList()); space.setBPD((cellBPD - usedBPD) / 2); space.setBidiLevel(getTableCell().getBidiLevelRecursive()); curBlockArea.addBlock(space); } else if (getTableCell().getDisplayAlign() == EN_AFTER) { Block space = new Block(); + space.setChangeBarList(getChangeBarList()); space.setBPD(cellBPD - usedBPD); space.setBidiLevel(getTableCell().getBidiLevelRecursive()); curBlockArea.addBlock(space); @@ -620,6 +622,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager { boolean outer, int level) { if (blocks[i][j] == null) { blocks[i][j] = new Block(); + blocks[i][j].setChangeBarList(getChangeBarList()); blocks[i][j].addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); blocks[i][j].setPositioning(Block.ABSOLUTE); blocks[i][j].setBidiLevel(level); @@ -651,6 +654,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager { int paddingEnd = padding.getPaddingEnd(false, this); Block block = new Block(); + block.setChangeBarList(getChangeBarList()); TraitSetter.setProducerID(block, getTable().getId()); block.setPositioning(Block.ABSOLUTE); block.setIPD(cellIPD + paddingStart + paddingEnd); @@ -677,6 +681,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager { public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); + curBlockArea.setChangeBarList(getChangeBarList()); curBlockArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); TraitSetter.setProducerID(curBlockArea, getTableCell().getId()); curBlockArea.setPositioning(Block.ABSOLUTE); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 4940c66b2..333419649 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -438,6 +438,8 @@ public class TableLayoutManager extends SpacedBorderedPaddedBlockLayoutManager public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); + curBlockArea.setChangeBarList(getChangeBarList()); + // Set up dimensions // Must get dimensions from parent area /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); diff --git a/fop-core/src/main/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/fop-core/src/main/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 552d9f92f..a078509e7 100644 --- a/fop-core/src/main/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/fop-core/src/main/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -736,6 +736,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { // save position and offset int saveIP = currentIPPosition; int saveBP = currentBPPosition; + int saveBO = getBeginOffset(); //Establish a new coordinate system AffineTransform at = new AffineTransform(); @@ -743,6 +744,8 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { at.translate(block.getXOffset(), block.getYOffset()); at.translate(0, block.getSpaceBefore()); + setBeginOffset(saveBO - block.getXOffset()); + if (!at.isIdentity()) { establishTransformationMatrix(at); } @@ -760,6 +763,8 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { restoreGraphicsState(); } + setBeginOffset(saveBO); + // stacked and relative blocks effect stacking currentIPPosition = saveIP; currentBPPosition = saveBP; diff --git a/fop-core/src/main/java/org/apache/fop/render/AbstractRenderer.java b/fop-core/src/main/java/org/apache/fop/render/AbstractRenderer.java index d57d3ce06..e8ab76d53 100644 --- a/fop-core/src/main/java/org/apache/fop/render/AbstractRenderer.java +++ b/fop-core/src/main/java/org/apache/fop/render/AbstractRenderer.java @@ -41,6 +41,7 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.BeforeFloat; import org.apache.fop.area.Block; +import org.apache.fop.area.BlockParent; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; import org.apache.fop.area.CTM; @@ -61,6 +62,7 @@ import org.apache.fop.area.inline.FilledArea; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.InlineBlock; import org.apache.fop.area.inline.InlineBlockParent; import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.inline.InlineViewport; @@ -70,7 +72,11 @@ import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.flow.ChangeBar; +import org.apache.fop.fo.properties.Property; import org.apache.fop.fonts.FontInfo; +import org.apache.fop.traits.BorderProps; +import org.apache.fop.traits.Direction; import org.apache.fop.traits.Visibility; /** @@ -111,7 +117,74 @@ public abstract class AbstractRenderer */ protected int containingIPPosition; - /** the currently active PageViewport */ + /** + * The "start edge" IP Position of the current column (for change bars) + */ + protected int columnStartIPPosition; + + /** + * The "end edge" IP Position of the current column (for change bars) + */ + protected int columnEndIPPosition; + + /** + * The "left" position of the current column (for change bars) + */ + protected int columnLeftIPPosition; + + /** + * The "right" position of the current column (for change bars) + */ + protected int columnRightIPPosition; + + /** + * The number of columns in the span (for change bars) + */ + protected int columnCount; + + /** + * The index number of the current column (for change bars) + */ + protected int columnIndex; + + /** + * The column width (for change bars) + */ + protected int columnWidth; + + /** + * The size of column gap (for change bars) + */ + protected int columnGap; + + /** + * The block progression direction (for change bars) + */ + protected Direction blockProgressionDirection; + + /** + * The inline progression direction (for change bars) + */ + protected Direction inlineProgressionDirection; + + /** + * Is binding on start edge of column? + */ + protected boolean bindingOnStartEdge; + + /** + * Is binding on end edge of column? + */ + protected boolean bindingOnEndEdge; + + /** + * The IP begin offset of coordinate 0 + */ + private int beginOffset; + + /** + * the currently active PageViewport + */ protected PageViewport currentPageViewport; /* warned XML handlers */ @@ -407,36 +480,95 @@ public abstract class AbstractRenderer * that are positioned into columns. *

* - * @param mr The main reference area + * @param mainReference The main reference area */ - protected void renderMainReference(MainReference mr) { + protected void renderMainReference(MainReference mainReference) { Span span = null; - List spans = mr.getSpans(); + List spans = mainReference.getSpans(); int saveBPPos = currentBPPosition; - int saveSpanBPPos = saveBPPos; int saveIPPos = currentIPPosition; + int saveSpanBPPos = saveBPPos; + for (Object span1 : spans) { span = (Span) span1; + + columnCount = span.getColumnCount(); + columnGap = span.getColumnGap(); + columnWidth = span.getColumnWidth(); + + blockProgressionDirection = (Direction) span.getTrait(Trait.BLOCK_PROGRESSION_DIRECTION); + inlineProgressionDirection = (Direction) span.getTrait(Trait.INLINE_PROGRESSION_DIRECTION); + int level = span.getBidiLevel(); if (level < 0) { level = 0; } if ((level & 1) == 1) { currentIPPosition += span.getIPD(); - currentIPPosition += mr.getColumnGap(); + currentIPPosition += columnGap; } - for (int c = 0; c < span.getColumnCount(); c++) { - NormalFlow flow = span.getNormalFlow(c); + + for (columnIndex = 0; columnIndex < columnCount; columnIndex++) { + + NormalFlow flow = span.getNormalFlow(columnIndex); + + boolean isLeftToRight = (inlineProgressionDirection == null) + || (inlineProgressionDirection.getEnumValue() == Constants.EN_LR); + if (flow != null) { + + // if direction is right to left, then end is left edge, + // else end is right edge (for top-bottom/bottom-top block + // progression directions) + + // binding edge is on left edge for odd pages and + // on right edge for even pages + + int pageIndex = currentPageViewport.getPageIndex(); + + bindingOnStartEdge = false; + bindingOnEndEdge = false; + + if (isLeftToRight) { + + columnStartIPPosition = 0; + columnEndIPPosition = columnWidth; + columnLeftIPPosition = 0; + columnRightIPPosition = columnWidth; + + if (blockProgressionDirection == null || blockProgressionDirection.isVertical()) { + if (pageIndex % 2 == 0) { + bindingOnStartEdge = true; + } else { + bindingOnEndEdge = true; + } + } + + } else { + + columnStartIPPosition = columnWidth; + columnEndIPPosition = 0; + columnLeftIPPosition = 0; + columnRightIPPosition = columnWidth; + + if (blockProgressionDirection == null || blockProgressionDirection.isVertical()) { + if (pageIndex % 2 == 0) { + bindingOnEndEdge = true; + } else { + bindingOnStartEdge = true; + } + } + } + currentBPPosition = saveSpanBPPos; if ((level & 1) == 1) { currentIPPosition -= flow.getIPD(); - currentIPPosition -= mr.getColumnGap(); + currentIPPosition -= columnGap; } renderFlow(flow); if ((level & 1) == 0) { currentIPPosition += flow.getIPD(); - currentIPPosition += mr.getColumnGap(); + currentIPPosition += columnGap; } } } @@ -504,7 +636,6 @@ public abstract class AbstractRenderer endVParea(); // clip if necessary - currentIPPosition = saveIP; currentBPPosition = saveBP; } else { @@ -584,6 +715,18 @@ public abstract class AbstractRenderer */ protected void renderBlock(Block block) { assert block != null; + List changeBarList = block.getChangeBarList(); + + if (changeBarList != null && !changeBarList.isEmpty()) { + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + drawChangeBars(block, changeBarList); + + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + List children = block.getChildAreas(); boolean inNewLayer = false; if (maybeStartLayer(block)) { @@ -627,8 +770,18 @@ public abstract class AbstractRenderer maybeEndLayer(block, inNewLayer); } + /** + * Renders an inline block area. + * + * @param inlineBlock The inline block area + */ + protected void renderInlineBlock(InlineBlock inlineBlock) { + renderBlock(inlineBlock.getBlock()); + } + /** * Establish new optional content group layer. + * * @param layer name of layer */ protected abstract void startLayer(String layer); @@ -699,6 +852,11 @@ public abstract class AbstractRenderer * @param inlineArea inline area text to render */ protected void renderInlineArea(InlineArea inlineArea) { + List changeBarList = inlineArea.getChangeBarList(); + + if (changeBarList != null && !changeBarList.isEmpty()) { + drawChangeBars(inlineArea, changeBarList); + } if (inlineArea instanceof TextArea) { renderText((TextArea) inlineArea); //} else if (inlineArea instanceof Character) { @@ -707,6 +865,8 @@ public abstract class AbstractRenderer renderWord((WordArea) inlineArea); } else if (inlineArea instanceof SpaceArea) { renderSpace((SpaceArea) inlineArea); + } else if (inlineArea instanceof InlineBlock) { + renderInlineBlock((InlineBlock) inlineArea); } else if (inlineArea instanceof InlineParent) { renderInlineParent((InlineParent) inlineArea); } else if (inlineArea instanceof InlineBlockParent) { @@ -757,6 +917,16 @@ public abstract class AbstractRenderer List children = text.getChildAreas(); int saveIP = currentIPPosition; int saveBP = currentBPPosition; + + List changeBarList = text.getChangeBarList(); + + if (changeBarList != null && !changeBarList.isEmpty()) { + drawChangeBars(text, changeBarList); + + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + for (Object aChildren : children) { InlineArea inline = (InlineArea) aChildren; renderInlineArea(inline); @@ -877,6 +1047,11 @@ public abstract class AbstractRenderer * (todo) Make renderImage() protected */ public void renderImage(Image image, Rectangle2D pos) { + List changeBarList = image.getChangeBarList(); + + if (changeBarList != null && !changeBarList.isEmpty()) { + drawChangeBars(image, changeBarList); + } // Default: do nothing. // Some renderers (ex. Text) don't support images. } @@ -903,6 +1078,12 @@ public abstract class AbstractRenderer * (todo) Make renderForeignObject() protected */ protected void renderForeignObject(ForeignObject fo, Rectangle2D pos) { + List changeBarList = fo.getChangeBarList(); + + if (changeBarList != null && !changeBarList.isEmpty()) { + drawChangeBars(fo, changeBarList); + } + // Default: do nothing. // Some renderers (ex. Text) don't support foreign objects. } @@ -975,4 +1156,191 @@ public abstract class AbstractRenderer matrix[5] = Math.round(matrix[5] * 1000); return new AffineTransform(matrix); } + + /** + * Draws all change bars associated with an area. + * + * @param area The area to draw change bars for + * @param changeBarList The list of change bars affecting the area + */ + protected void drawChangeBars(Area area, List changeBarList) { + + if (area.getTraitAsBoolean(Trait.IS_REFERENCE_AREA)) { + return; + } + + Block changeBarArea; + + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + int currentColumnStartIP = columnStartIPPosition; + int currentColumnEndIP = columnEndIPPosition; + int currentColumnLeftIP = columnLeftIPPosition; + int currentColumnRightIP = columnRightIPPosition; + + for (ChangeBar changeBar : changeBarList) { + + boolean isLeftToRight = (inlineProgressionDirection == null) + || (inlineProgressionDirection.getEnumValue() == Constants.EN_LR); + + changeBarArea = new Block(); + + // currentIPPosition is reset to zero so from now on all multicolumn + // dimensions has to be calculated relatively to the given column + currentIPPosition = 0; + currentBPPosition = saveBP; + + int changeBarWidth = changeBar.getWidth().getValue(); + int changeBarOffset = changeBar.getOffset().getValue(); + + if (isLeftToRight) { + currentColumnStartIP = columnStartIPPosition - changeBarWidth; + currentColumnLeftIP = columnLeftIPPosition - changeBarWidth; + } else { + currentColumnEndIP = columnEndIPPosition - changeBarWidth; + currentColumnLeftIP = columnLeftIPPosition - changeBarWidth; + } + + // xOffset by default is negative width for change bars placed on the + // start edge (overriden if placement is at the end edge) + int xOffset = currentColumnStartIP; + + // xScale is for adding or subtracting the offset of the change bar + // depending on placing the bar towards or away from the edge it is + // bound to + int xScale = -1; + + // determines currentIPPosition based on placement + switch (changeBar.getPlacement()) { + case EN_START: + xOffset = currentColumnStartIP; + xScale = -1; + break; + case EN_END: + xOffset = currentColumnEndIP; + xScale = 1; + break; + case EN_LEFT: + xOffset = currentColumnLeftIP; + xScale = (isLeftToRight) ? -1 : 1; + break; + case EN_RIGHT: + xOffset = currentColumnRightIP; + xScale = (isLeftToRight) ? 1 : -1; + break; + case EN_INSIDE: + if (bindingOnStartEdge) { + xOffset = currentColumnStartIP; + xScale = -1; + } else if (bindingOnEndEdge) { + xOffset = currentColumnEndIP; + xScale = 1; + } else { + xOffset = currentColumnStartIP; + xScale = -1; + } + break; + case EN_OUTSIDE: + if (bindingOnStartEdge) { + xOffset = columnEndIPPosition; + xScale = 1; + } else if (bindingOnEndEdge) { + xOffset = columnStartIPPosition; + xScale = -1; + } else { + xOffset = columnStartIPPosition; + xScale = -1; + } + break; + case EN_ALTERNATE: + if (columnCount == 2) { + if (columnIndex == 0) { + xOffset = columnStartIPPosition; + xScale = -1; + } else { + xOffset = columnEndIPPosition; + xScale = 1; + } + } else { + if (bindingOnStartEdge) { + xOffset = columnEndIPPosition; + xScale = 1; + } else if (bindingOnEndEdge) { + xOffset = columnStartIPPosition; + xScale = -1; + } else { + xOffset = columnStartIPPosition; + xScale = -1; + } + } + break; + default: + break; + } + + if (isLeftToRight) { + xOffset += xScale * changeBarOffset; + } else { + xOffset -= xScale * changeBarOffset; + } + + xOffset += getBeginOffset(); + + // Change bar area has 0 ipd, class xsl-absolute, no margin or padding + changeBarArea.setAreaClass(Area.CLASS_ABSOLUTE); + changeBarArea.setIPD(0); + + BorderProps props = BorderProps.makeRectangular( + changeBar.getStyle(), changeBarWidth, changeBar.getColor(), + BorderProps.Mode.SEPARATE); + + changeBarArea.addTrait(Trait.BORDER_START, props); + changeBarArea.addTrait(Trait.BORDER_END, props); + + changeBarArea.setXOffset(xOffset); + + int areaHeight = area.getAllocBPD(); + + if (area instanceof BlockParent) { + changeBarArea.setBPD(areaHeight); + changeBarArea.setYOffset(((BlockParent) area).getYOffset()); + renderBlock(changeBarArea); + + } else { + if (areaHeight > 0) { + Property p = changeBar.getLineHeight().getOptimum(DummyPercentBaseContext.getInstance()); + int lineHeight = p.getLength().getValue(); + changeBarArea.setBPD(lineHeight); + changeBarArea.setYOffset(areaHeight - lineHeight); + } + renderInlineBlock(new InlineBlock(changeBarArea)); + } + + // restore position on page + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + } + + /** + * Returns the begin offset of the inline begin (changes by reference area + * transforms). + * + * @return the offset from current coordinate system 0 that the IP begin is + * at + */ + protected int getBeginOffset() { + return beginOffset; + } + + /** + * Sets the begin offset for inline progression begin (changes by reference + * area tranforms). + * + * @param offset the new offset from IPP 0 that true IP start is at + */ + protected void setBeginOffset(int offset) { + beginOffset = offset; + } } diff --git a/fop-core/src/main/java/org/apache/fop/render/xml/XMLRenderer.java b/fop-core/src/main/java/org/apache/fop/render/xml/XMLRenderer.java index f8765f280..ecad6b500 100644 --- a/fop-core/src/main/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/fop-core/src/main/java/org/apache/fop/render/xml/XMLRenderer.java @@ -72,6 +72,7 @@ import org.apache.fop.area.inline.Container; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.InlineBlock; import org.apache.fop.area.inline.InlineBlockParent; import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.inline.InlineViewport; @@ -692,6 +693,26 @@ public class XMLRenderer extends AbstractXMLRenderer { endElement("block"); } + /** {@inheritDoc} */ + @Override + protected void renderInlineBlock(InlineBlock inlineBlock) { + Block block = inlineBlock.getBlock(); + atts.clear(); + addAreaAttributes(block); + addTraitAttributes(block); + if (block.getXOffset() != 0) { + addAttribute("left-offset", block.getXOffset()); + } + if (block.getYOffset() != 0) { + addAttribute("top-offset", block.getYOffset()); + } + startElement("inlineblock", atts); + if (block.getChildAreas() != null) { + renderBlocks(null, block.getChildAreas()); + } + endElement("inlineblock"); + } + /** * {@inheritDoc} */ @@ -943,6 +964,4 @@ public class XMLRenderer extends AbstractXMLRenderer { addAttribute("reversed", "true"); } } - - } diff --git a/fop/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-datatypes.xsd b/fop/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-datatypes.xsd index e25556f9b..e4865f2d2 100644 --- a/fop/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-datatypes.xsd +++ b/fop/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-datatypes.xsd @@ -67,6 +67,8 @@ + + @@ -79,6 +81,8 @@ + + @@ -92,7 +96,7 @@ - + diff --git a/fop/test/layoutengine/standard-testcases/change-bar_block.xml b/fop/test/layoutengine/standard-testcases/change-bar_block.xml new file mode 100644 index 000000000..9277343b5 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/change-bar_block.xml @@ -0,0 +1,73 @@ + + + + + +

This test checks fo:change-bar-* on block elements.

+
+ + + + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fop/test/layoutengine/standard-testcases/change-bar_inline.xml b/fop/test/layoutengine/standard-testcases/change-bar_inline.xml new file mode 100644 index 000000000..d90500db8 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/change-bar_inline.xml @@ -0,0 +1,81 @@ + + + + + +

This test checks fo:change-bar-* on inline elements.

+
+ + + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore + magna + aliqua. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore + magna + aliqua. + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fop/test/layoutengine/standard-testcases/change-bar_list.xml b/fop/test/layoutengine/standard-testcases/change-bar_list.xml new file mode 100644 index 000000000..f1219fc84 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/change-bar_list.xml @@ -0,0 +1,90 @@ + + + + + +

This test checks fo:change-bar-* on list elements.

+
+ + + + + + + + + + + + + + + + + 1 + + + First + + + + + + + 2 + + + + + Second + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fop/test/layoutengine/standard-testcases/change-bar_overlapped.xml b/fop/test/layoutengine/standard-testcases/change-bar_overlapped.xml new file mode 100644 index 000000000..240670773 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/change-bar_overlapped.xml @@ -0,0 +1,95 @@ + + + + + +

This test checks fo:change-bar-* on list elements.

+
+ + + + + + + + + + + + + + January February March April May June July + August September October + November December + + + January + February + March + + April + May + + + + June + + + + July + August + + + September + October + November + December + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fop/test/layoutengine/standard-testcases/change-bar_placement-rtl.xml b/fop/test/layoutengine/standard-testcases/change-bar_placement-rtl.xml new file mode 100644 index 000000000..f9b5b197e --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/change-bar_placement-rtl.xml @@ -0,0 +1,226 @@ + + + + + +

This test checks fo:change-bar-start placement.

+
+ + + + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + Lorem ipsum dolor sit + amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore + et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fop/test/layoutengine/standard-testcases/change-bar_placement.xml b/fop/test/layoutengine/standard-testcases/change-bar_placement.xml new file mode 100644 index 000000000..82d4bd9fa --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/change-bar_placement.xml @@ -0,0 +1,226 @@ + + + + + +

This test checks fo:change-bar-start placement.

+
+ + + + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + + + + Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. + Lorem ipsum dolor sit + amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore + et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fop/test/layoutengine/standard-testcases/change-bar_style.xml b/fop/test/layoutengine/standard-testcases/change-bar_style.xml new file mode 100644 index 000000000..65203cfeb --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/change-bar_style.xml @@ -0,0 +1,102 @@ + + + + + +

This test checks fo:change-bar-start style.

+
+ + + + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + +
diff --git a/fop/test/layoutengine/standard-testcases/change-bar_table.xml b/fop/test/layoutengine/standard-testcases/change-bar_table.xml new file mode 100644 index 000000000..39bd4b8b1 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/change-bar_table.xml @@ -0,0 +1,147 @@ + + + + + +

This test checks fo:change-bar-* on table elements.

+
+ + + + + + + + + + + + + + + + header-row1-col1 + + + header-row1-col2 + + + + + + + header-row2-col1 + + + + + header-row2-col2 + + + + + + + + + + footer-row1-col1 + + + + footer-row1-col2 + + + + + footer-row2-col1 + + + footer-row2-col2 + + + + + + + + + body-row1-col1 + + + body-row1-col2 + + + + + + + body-row2-col1 + + + + + body-row2-col2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +