diff options
14 files changed, 994 insertions, 360 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java b/fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java index d20e4d37a..3ba4babb7 100644 --- a/fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java +++ b/fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java @@ -54,6 +54,7 @@ import org.apache.fop.fo.flow.RetrieveTableMarker; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableFooter; @@ -358,6 +359,24 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler { super.endTable(tbl); } + public void startTableCaption(final TableCaption tableCaption) { + startContent(new Event(this) { + public void run() { + eventHandler.startTableCaption(tableCaption); + } + }, true); + super.startTableCaption(tableCaption); + } + + public void endTableCaption(final TableCaption tableCaption) { + endContent(new Event(this) { + public void run() { + eventHandler.endTableCaption(tableCaption); + } + }); + super.endTableCaption(tableCaption); + } + @Override public void startColumn(final TableColumn tc) { startContent(new Event(this) { diff --git a/fop-core/src/main/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java b/fop-core/src/main/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java index 8def8a4d4..160a0236e 100644 --- a/fop-core/src/main/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java +++ b/fop-core/src/main/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java @@ -58,6 +58,7 @@ import org.apache.fop.fo.flow.RetrieveTableMarker; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableFooter; import org.apache.fop.fo.flow.table.TableHeader; @@ -258,6 +259,14 @@ class StructureTreeEventTrigger extends FOEventHandler { tables.pop(); } + public void startTableCaption(TableCaption tableCaption) { + startElement(tableCaption); + } + + public void endTableCaption(TableCaption tableCaption) { + endElement(tableCaption); + } + @Override public void startHeader(TableHeader header) { inTableHeader.push(Boolean.TRUE); diff --git a/fop-core/src/main/java/org/apache/fop/fo/DelegatingFOEventHandler.java b/fop-core/src/main/java/org/apache/fop/fo/DelegatingFOEventHandler.java index 4cf6ddd15..2e240fe35 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/DelegatingFOEventHandler.java +++ b/fop-core/src/main/java/org/apache/fop/fo/DelegatingFOEventHandler.java @@ -46,6 +46,7 @@ import org.apache.fop.fo.flow.RetrieveTableMarker; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableFooter; @@ -204,6 +205,14 @@ public abstract class DelegatingFOEventHandler extends FOEventHandler { delegate.endTable(tbl); } + public void startTableCaption(TableCaption tableCaption) { + delegate.startTableCaption(tableCaption); + } + + public void endTableCaption(TableCaption tableCaption) { + delegate.endTableCaption(tableCaption); + } + @Override public void startColumn(TableColumn tc) { delegate.startColumn(tc); diff --git a/fop-core/src/main/java/org/apache/fop/fo/FOEventHandler.java b/fop-core/src/main/java/org/apache/fop/fo/FOEventHandler.java index 0be90dd04..1f1611fb4 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/FOEventHandler.java +++ b/fop-core/src/main/java/org/apache/fop/fo/FOEventHandler.java @@ -46,6 +46,7 @@ import org.apache.fop.fo.flow.RetrieveTableMarker; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableFooter; @@ -283,6 +284,12 @@ public abstract class FOEventHandler { public void endTable(Table tbl) { } + public void startTableCaption(TableCaption tableCaption) { + } + + public void endTableCaption(TableCaption tableCaption) { + } + /** * * @param tc TableColumn that is starting; diff --git a/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableAndCaption.java b/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableAndCaption.java index b7c7adc91..35ec4c617 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableAndCaption.java +++ b/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableAndCaption.java @@ -19,7 +19,6 @@ package org.apache.fop.fo.flow.table; -// XML import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; @@ -29,6 +28,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonAccessibility; import org.apache.fop.fo.properties.CommonAccessibilityHolder; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.KeepProperty; /** * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-and-caption"> @@ -37,25 +38,13 @@ import org.apache.fop.fo.properties.CommonAccessibilityHolder; */ public class TableAndCaption extends FObj implements CommonAccessibilityHolder { + private static final String TABLE_CAPTION = "fo:table-caption"; + private static final String TABLE = "fo:table"; private CommonAccessibility commonAccessibility; - - // The value of properties relevant for fo:table-and-caption. - // Unused but valid items, commented out for performance: - // private CommonAural commonAural; - // private CommonBorderPaddingBackground commonBorderPaddingBackground; - // private CommonMarginBlock commonMarginBlock; - // private CommonRelativePosition commonRelativePosition; - // private int breakAfter; - // private int breakBefore; - // private int captionSide; - // private int intrusionDisplace; - // private KeepProperty keepTogether; - // private KeepProperty keepWithNext; - // private KeepProperty keepWithPrevious; - // private int textAlign; - // End of property values - - static boolean notImplementedWarningGiven; + private CommonBorderPaddingBackground commonBorderPaddingBackground; + private KeepProperty keepTogether; + private KeepProperty keepWithNext; + private KeepProperty keepWithPrevious; /** used for FO validation */ private boolean tableCaptionFound; @@ -68,19 +57,16 @@ public class TableAndCaption extends FObj implements CommonAccessibilityHolder { */ public TableAndCaption(FONode parent) { super(parent); - - if (!notImplementedWarningGiven) { - getFOValidationEventProducer().unimplementedFeature(this, getName(), - "fo:table-and-caption", getLocator()); - // @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD") - notImplementedWarningGiven = true; - } } @Override public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonAccessibility = CommonAccessibility.getInstance(pList); + keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); + keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep(); + keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); + commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); } /** @@ -104,21 +90,21 @@ public class TableAndCaption extends FObj implements CommonAccessibilityHolder { if (FO_URI.equals(nsURI)) { if (localName.equals("marker")) { if (tableCaptionFound) { - nodesOutOfOrderError(loc, "fo:marker", "fo:table-caption"); + nodesOutOfOrderError(loc, "fo:marker", TABLE_CAPTION); } else if (tableFound) { - nodesOutOfOrderError(loc, "fo:marker", "fo:table"); + nodesOutOfOrderError(loc, "fo:marker", TABLE); } } else if (localName.equals("table-caption")) { if (tableCaptionFound) { - tooManyNodesError(loc, "fo:table-caption"); + tooManyNodesError(loc, TABLE_CAPTION); } else if (tableFound) { - nodesOutOfOrderError(loc, "fo:table-caption", "fo:table"); + nodesOutOfOrderError(loc, TABLE_CAPTION, TABLE); } else { tableCaptionFound = true; } } else if (localName.equals("table")) { if (tableFound) { - tooManyNodesError(loc, "fo:table"); + tooManyNodesError(loc, TABLE); } else { tableFound = true; } @@ -146,5 +132,20 @@ public class TableAndCaption extends FObj implements CommonAccessibilityHolder { return commonAccessibility; } + public KeepProperty getKeepTogether() { + return keepTogether; + } + + public KeepProperty getKeepWithNext() { + return keepWithNext; + } + + public KeepProperty getKeepWithPrevious() { + return keepWithPrevious; + } + + public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { + return commonBorderPaddingBackground; + } } diff --git a/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableCaption.java b/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableCaption.java index 5ecce65af..5ca8c51de 100644 --- a/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableCaption.java +++ b/fop-core/src/main/java/org/apache/fop/fo/flow/table/TableCaption.java @@ -19,17 +19,19 @@ package org.apache.fop.fo.flow.table; -// XML import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonAccessibility; import org.apache.fop.fo.properties.CommonAccessibilityHolder; - +import org.apache.fop.fo.properties.EnumProperty; +import org.apache.fop.fo.properties.KeepProperty; +import org.apache.fop.fo.properties.Property; /** * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-caption"> @@ -38,24 +40,13 @@ import org.apache.fop.fo.properties.CommonAccessibilityHolder; public class TableCaption extends FObj implements CommonAccessibilityHolder { private CommonAccessibility commonAccessibility; - - // The value of properties relevant for fo:table-caption. - // Unused but valid items, commented out for performance: - // private CommonAural commonAural; - // private CommonRelativePosition commonRelativePosition; - // private LengthRangeProperty blockProgressionDimension; - // private Length height; - // private LengthRangeProperty inlineProgressionDimension; - // private int intrusionDisplace; - // private KeepProperty keepTogether; - // private Length width; - // End of property values + private KeepProperty keepTogether; + private KeepProperty keepWithNext; + private KeepProperty keepWithPrevious; /** used for FO validation */ private boolean blockItemFound; - static boolean notImplementedWarningGiven; - /** * Create a TableCaption instance with the given {@link FONode} * as parent. @@ -63,19 +54,25 @@ public class TableCaption extends FObj implements CommonAccessibilityHolder { */ public TableCaption(FONode parent) { super(parent); - - if (!notImplementedWarningGiven) { - getFOValidationEventProducer().unimplementedFeature(this, getName(), - "fo:table-caption", getLocator()); - // @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD") - notImplementedWarningGiven = true; - } } /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonAccessibility = CommonAccessibility.getInstance(pList); + keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); + Property keepWithNextProp = pList.get(PR_KEEP_WITH_NEXT); + if (keepWithNextProp instanceof KeepProperty) { + ((KeepProperty)keepWithNextProp).setWithinPage( + EnumProperty.getInstance(Constants.EN_ALWAYS, "ALWAYS"), true); + } + keepWithNext = keepWithNextProp.getKeep(); + keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); + } + + public void startOfNode() throws FOPException { + super.startOfNode(); + getFOEventHandler().startTableCaption(this); } /** {@inheritDoc} */ @@ -83,6 +80,7 @@ public class TableCaption extends FObj implements CommonAccessibilityHolder { if (firstChild == null) { missingChildElementError("marker* (%block;)"); } + getFOEventHandler().endTableCaption(this); } /** @@ -122,5 +120,16 @@ public class TableCaption extends FObj implements CommonAccessibilityHolder { return commonAccessibility; } + public KeepProperty getKeepTogether() { + return keepTogether; + } + + public KeepProperty getKeepWithNext() { + return keepWithNext; + } + + public KeepProperty getKeepWithPrevious() { + return keepWithPrevious; + } } 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 8be8b5803..d4feedf82 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 @@ -62,7 +62,9 @@ import org.apache.fop.fo.flow.RetrieveMarker; import org.apache.fop.fo.flow.RetrieveTableMarker; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.fo.flow.table.Table; +import org.apache.fop.fo.flow.table.TableAndCaption; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableFooter; @@ -91,6 +93,8 @@ import org.apache.fop.layoutmgr.inline.TextLayoutManager; import org.apache.fop.layoutmgr.inline.WrapperLayoutManager; import org.apache.fop.layoutmgr.list.ListBlockLayoutManager; import org.apache.fop.layoutmgr.list.ListItemLayoutManager; +import org.apache.fop.layoutmgr.table.TableAndCaptionLayoutManager; +import org.apache.fop.layoutmgr.table.TableCaptionLayoutManager; import org.apache.fop.layoutmgr.table.TableLayoutManager; import org.apache.fop.util.CharUtilities; @@ -143,6 +147,8 @@ public class LayoutManagerMapping implements LayoutManagerMaker { new PageNumberCitationLayoutManagerMaker()); registerMaker(PageNumberCitationLast.class, new PageNumberCitationLastLayoutManagerMaker()); + registerMaker(TableAndCaption.class, new TableAndCaptionManagerMaker()); + registerMaker(TableCaption.class, new TableCaptionManagerMaker()); registerMaker(Table.class, new TableLayoutManagerMaker()); registerMaker(TableBody.class, new Maker()); registerMaker(TableColumn.class, new Maker()); @@ -458,6 +464,18 @@ public class LayoutManagerMapping implements LayoutManagerMaker { } } + public class TableAndCaptionManagerMaker extends Maker { + public void make(FONode node, List layoutManagers, FOUserAgent userAgent) { + layoutManagers.add(new TableAndCaptionLayoutManager((TableAndCaption)node)); + } + } + + public class TableCaptionManagerMaker extends Maker { + public void make(FONode node, List layoutManagers, FOUserAgent userAgent) { + layoutManagers.add(new TableCaptionLayoutManager((TableCaption)node)); + } + } + public class MultiSwitchLayoutManagerMaker extends Maker { @Override 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 1d8cb890c..2f974c2ac 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 @@ -19,13 +19,33 @@ package org.apache.fop.layoutmgr.table; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Stack; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; +import org.apache.fop.area.LineArea; +import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.table.TableAndCaption; -import org.apache.fop.layoutmgr.BlockStackingLayoutManager; -import org.apache.fop.layoutmgr.Keep; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.KeepProperty; +import org.apache.fop.layoutmgr.BreakOpportunity; +import org.apache.fop.layoutmgr.KnuthElement; +import org.apache.fop.layoutmgr.KnuthPossPosIter; +import org.apache.fop.layoutmgr.LMiter; import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.ListElement; +import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.SpacedBorderedPaddedBlockLayoutManager; +import org.apache.fop.layoutmgr.TraitSetter; +import org.apache.fop.traits.MinOptMax; /** * LayoutManager for a table-and-caption FO. @@ -35,130 +55,255 @@ import org.apache.fop.layoutmgr.PositionIterator; * The caption blocks have an implicit keep with the table. * TODO Implement getNextKnuthElements() */ -public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { - +public class TableAndCaptionLayoutManager extends SpacedBorderedPaddedBlockLayoutManager implements BreakOpportunity { private Block curBlockArea; + /** Iterator over the child layout managers. */ + private ProxyLMiter proxyLMiter; + /** * Create a new table and caption layout manager. - * @param node table-and-caption FO + * @param tableAndCaption the block FO object to create the layout manager for. */ - public TableAndCaptionLayoutManager(TableAndCaption node) { - super(node); + public TableAndCaptionLayoutManager(TableAndCaption tableAndCaption) { + super(tableAndCaption); + proxyLMiter = new ProxyLMiter(); } - /** - * Returns the table-and-caption formatting object. - * @return the table-and-caption formatting object - */ - public TableAndCaption getTableAndCaptionFO() { - return (TableAndCaption)this.fobj; + @Override + protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() { + return getTableAndCaptionFO().getCommonBorderPaddingBackground(); + } + + public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) { + return getNextKnuthElements(context, alignment, null, null, null); + } + + public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack, + Position restartPosition, LayoutManager restartAtLM) { + resetSpaces(); + return super.getNextKnuthElements(context, alignment, lmStack, restartPosition, restartAtLM); + } + + private void resetSpaces() { + this.discardBorderBefore = false; + this.discardBorderAfter = false; + this.discardPaddingBefore = false; + this.discardPaddingAfter = false; + this.effSpaceBefore = null; + this.effSpaceAfter = null; } /** - * Get the next break possibility. - * - * @param context the layout context for getting breaks - * @return the next break possibility + * Proxy iterator for Block LM. + * This iterator creates and holds the complete list + * of child LMs. + * It uses fobjIter as its base iterator. + * Block LM's createNextChildLMs uses this iterator + * as its base iterator. */ - /* - public BreakPoss getNextBreakPoss(LayoutContext context) { - LayoutManager curLM; // currently active LM - - MinOptMax stackSize = new MinOptMax(); - // if starting add space before - // stackSize.add(spaceBefore); - BreakPoss lastPos = null; - - // if there is a caption then get the side and work out when - // to handle it - - while ((curLM = getChildLM()) != null) { - // Make break positions and return blocks! - // Set up a LayoutContext - int ipd = context.getRefIPD(); - BreakPoss bp; - - LayoutContext childLC = LayoutContext.newInstance(); - // if line layout manager then set stack limit to ipd - // line LM actually generates a LineArea which is a block - childLC.setStackLimit( - MinOptMax.subtract(context.getStackLimit(), - stackSize)); - childLC.setRefIPD(ipd); - - boolean over = false; - while (!curLM.isFinished()) { - if ((bp = curLM.getNextBreakPoss(childLC)) != null) { - if (stackSize.opt + bp.getStackingSize().opt > context.getStackLimit().max) { - // reset to last break - if (lastPos != null) { - LayoutManager lm = lastPos.getLayoutManager(); - lm.resetPosition(lastPos.getPosition()); - if (lm != curLM) { - curLM.resetPosition(null); - } - } else { - curLM.resetPosition(null); - } - over = true; - break; - } - stackSize.add(bp.getStackingSize()); - lastPos = bp; - childBreaks.add(bp); - - if (bp.nextBreakOverflows()) { - over = true; - break; - } - - childLC.setStackLimit(MinOptMax.subtract( - context.getStackLimit(), stackSize)); - } + protected class ProxyLMiter extends LMiter { + + /** + * Constructs a proxy iterator for Block LM. + */ + public ProxyLMiter() { + super(TableAndCaptionLayoutManager.this); + listLMs = new ArrayList<>(10); + } + + /** + * @return true if there are more child lms + */ + public boolean hasNext() { + return (curPos < listLMs.size()) || createNextChildLMs(curPos); + } + + /** + * @param pos ... + * @return true if new child lms were added + */ + protected boolean createNextChildLMs(int pos) { + List<LayoutManager> newLMs = createChildLMs(pos + 1 - listLMs.size()); + if (newLMs != null) { + listLMs.addAll(newLMs); } - BreakPoss breakPoss = new BreakPoss( - new LeafPosition(this, childBreaks.size() - 1)); - if (over) { - breakPoss.setFlag(BreakPoss.NEXT_OVERFLOWS, true); + return pos < listLMs.size(); + } + } + + public boolean createNextChildLMs(int pos) { + while (proxyLMiter.hasNext()) { + LayoutManager lm = proxyLMiter.next(); + addChildLM(lm); + if (pos < childLMs.size()) { + return true; } - breakPoss.setStackingSize(stackSize); - return breakPoss; } - setFinished(true); - return null; - }*/ + return false; + } - /** - * Add the areas. - * - * @param parentIter the position iterator - * @param layoutContext the layout context for adding areas - */ - public void addAreas(PositionIterator parentIter, - LayoutContext layoutContext) { + public KeepProperty getKeepTogetherProperty() { + return getTableAndCaptionFO().getKeepTogether(); + } + + public KeepProperty getKeepWithPreviousProperty() { + return getTableAndCaptionFO().getKeepWithPrevious(); + } + + public KeepProperty getKeepWithNextProperty() { + return getTableAndCaptionFO().getKeepWithNext(); + } + + public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - addId(); - /* TODO: Reimplement using Knuth approach + // if this will create the first block area in a page + // and display-align is after or center, add space before + if (layoutContext.getSpaceBefore() > 0) { + addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore())); + } + LayoutManager childLM; - int iStartPos = 0; - LayoutContext lc = LayoutContext.newInstance(); + LayoutManager lastLM = null; + LayoutContext lc = LayoutContext.offspringOf(layoutContext); + lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); + // set space after in the LayoutContext for children + if (layoutContext.getSpaceAfter() > 0) { + lc.setSpaceAfter(layoutContext.getSpaceAfter()); + } + PositionIterator childPosIter; + + // "unwrap" the NonLeafPositions stored in parentIter + // and put them in a new list; + LinkedList<Position> positionList = new LinkedList<>(); + Position pos; + boolean spaceBefore = false; + boolean spaceAfter = false; + Position firstPos = null; + Position lastPos = null; while (parentIter.hasNext()) { - LeafPosition lfp = (LeafPosition) parentIter.next(); - // Add the block areas to Area - PositionIterator breakPosIter = new BreakPossPosIter( - childBreaks, iStartPos, lfp.getLeafPos() + 1); - iStartPos = lfp.getLeafPos() + 1; - while ((childLM = breakPosIter.getNextChildLM()) != null) { - childLM.addAreas(breakPosIter, lc); + pos = parentIter.next(); + if (pos.getIndex() >= 0) { + if (firstPos == null) { + firstPos = pos; + } + lastPos = pos; + } + Position innerPosition = pos; + if (pos instanceof NonLeafPosition) { + //Not all elements are wrapped + innerPosition = pos.getPosition(); + } + if (innerPosition == null) { + // pos was created by this BlockLM and was inside an element + // representing space before or after + // this means the space was not discarded + if (positionList.isEmpty()) { + // pos was in the element representing space-before + spaceBefore = true; + } else { + // pos was in the element representing space-after + spaceAfter = true; + } + } else if (innerPosition.getLM() == this + && !(innerPosition instanceof MappingPosition)) { + // pos was created by this BlockLM and was inside a penalty + // allowing or forbidding a page break + // nothing to do + } else { + // innerPosition was created by another LM + positionList.add(innerPosition); + lastLM = innerPosition.getLM(); + } + } + + addId(); + + registerMarkers(true, isFirst(firstPos), isLast(lastPos)); + + if (bpUnit == 0) { + // the Positions in positionList were inside the elements + // created by the LineLM + childPosIter = new StackingIter(positionList.listIterator()); + } else { + // the Positions in positionList were inside the elements + // created by the BlockLM in the createUnitElements() method + LinkedList<KnuthElement> splitList = new LinkedList<>(); + int splitLength = 0; + int iFirst = ((MappingPosition) positionList.getFirst()).getFirstIndex(); + int iLast = ((MappingPosition) positionList.getLast()).getLastIndex(); + // copy from storedList to splitList all the elements from + // iFirst to iLast + ListIterator<KnuthElement> storedListIterator = storedList.listIterator(iFirst); + while (storedListIterator.nextIndex() <= iLast) { + KnuthElement element = storedListIterator.next(); + // some elements in storedList (i.e. penalty items) were created + // by this BlockLM, and must be ignored + if (element.getLayoutManager() != this) { + splitList.add(element); + splitLength += element.getWidth(); + lastLM = element.getLayoutManager(); + } } - }*/ + // add space before and / or after the paragraph + // to reach a multiple of bpUnit + if (spaceBefore && spaceAfter) { + adjustedSpaceBefore = (neededUnits(splitLength + + foSpaceBefore.getMin() + + foSpaceAfter.getMin()) + * bpUnit - splitLength) / 2; + adjustedSpaceAfter = neededUnits(splitLength + + foSpaceBefore.getMin() + + foSpaceAfter.getMin()) + * bpUnit - splitLength - adjustedSpaceBefore; + } else if (spaceBefore) { + adjustedSpaceBefore = neededUnits(splitLength + + foSpaceBefore.getMin()) + * bpUnit - splitLength; + } else { + adjustedSpaceAfter = neededUnits(splitLength + + foSpaceAfter.getMin()) + * bpUnit - splitLength; + } + childPosIter = new KnuthPossPosIter(splitList, 0, splitList + .size()); + } + while ((childLM = childPosIter.getNextChildLM()) != null) { + // set last area flag + lc.setFlags(LayoutContext.LAST_AREA, + (layoutContext.isLastArea() && childLM == lastLM)); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); + // Add the line areas to Area + childLM.addAreas(childPosIter, lc); + } + + registerMarkers(false, isFirst(firstPos), isLast(lastPos)); + + TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), + effSpaceBefore, effSpaceAfter); flush(); - //childBreaks.clear(); curBlockArea = null; + resetSpaces(); + + //Notify end of block layout manager to the PSLM + checkEndOfLayout(lastPos); + } + + private static class StackingIter extends PositionIterator { + public StackingIter(Iterator parentIter) { + super(parentIter); + } + + protected LayoutManager getLM(Object nextObj) { + return ((Position) nextObj).getLM(); + } + + protected Position getPos(Object nextObj) { + return ((Position) nextObj); + } } /** @@ -170,54 +315,98 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { * Finally, based on the dimensions of the parent area, it initializes * its own area. This includes setting the content IPD and the maximum * BPD. - * - * @param childArea the child area to locate the parent - * @return the area for this table and caption + * @param childArea area to get the parent area for + * @return the parent area */ public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); - curBlockArea.setChangeBarList(getChangeBarList()); - // Set up dimensions + curBlockArea.setIPD(super.getContentAreaIPD()); + + curBlockArea.setBidiLevel(getTableAndCaptionFO().getBidiLevelRecursive()); + // Must get dimensions from parent area - Area parentArea = parentLayoutManager.getParentArea(curBlockArea); - int referenceIPD = parentArea.getIPD(); - curBlockArea.setIPD(referenceIPD); - curBlockArea.setBidiLevel(getTableAndCaptionFO().getBidiLevel()); - // Get reference IPD from parentArea + //Don't optimize this line away. It can have ugly side-effects. + parentLayoutManager.getParentArea(curBlockArea); + + // set traits + TraitSetter.setProducerID(curBlockArea, getTableAndCaptionFO().getId()); + TraitSetter.addBorders(curBlockArea, + getCommonBorderPaddingBackground(), + discardBorderBefore, discardBorderAfter, false, false, this); + TraitSetter.addPadding(curBlockArea, + getCommonBorderPaddingBackground(), + discardPaddingBefore, discardPaddingAfter, false, false, this); + TraitSetter.addMargins(curBlockArea, + getCommonBorderPaddingBackground(), + startIndent, endIndent, + this); + TraitSetter.setLayer(curBlockArea, getTableAndCaptionFO().getLayer()); + curBlockArea.setLocation(FONode.getLocatorString(getTableAndCaptionFO().getLocator())); setCurrentArea(curBlockArea); // ??? for generic operations } return curBlockArea; } + public void addChildArea(Area childArea) { + if (curBlockArea != null) { + if (childArea instanceof LineArea) { + curBlockArea.addLineArea((LineArea) childArea); + } else { + curBlockArea.addBlock((Block) childArea); + } + } + } + /** - * Add the child to the current area. - * - * @param childArea the area to add + * Force current area to be added to parent area. + * {@inheritDoc} */ - public void addChildArea(Area childArea) { + protected void flush() { + if (curBlockArea != null) { + TraitSetter.addBackground(curBlockArea, getTableAndCaptionFO().getCommonBorderPaddingBackground(), this); + super.flush(); + } + } + + /** + * Returns the table-and-caption formatting object. + * @return the table-and-caption formatting object + */ + protected TableAndCaption getTableAndCaptionFO() { + return (TableAndCaption) fobj; + } + + // --------- Property Resolution related functions --------- // + + /** + * Returns the IPD of the content area + * @return the IPD of the content area + */ + public int getContentAreaIPD() { if (curBlockArea != null) { - curBlockArea.addBlock((Block) childArea); + return curBlockArea.getIPD(); } + return super.getContentAreaIPD(); } - /** {@inheritDoc} */ - public Keep getKeepWithNext() { - return Keep.KEEP_AUTO; - /* TODO Complete me! - return KeepUtil.getCombinedBlockLevelKeepStrength( - getTableAndCaptionFO().getKeepWithNext()); - */ + /** + * Returns the BPD of the content area + * @return the BPD of the content area + */ + public int getContentAreaBPD() { + if (curBlockArea != null) { + return curBlockArea.getBPD(); + } + return -1; } - /** {@inheritDoc} */ - public Keep getKeepWithPrevious() { - return Keep.KEEP_AUTO; - /* TODO Complete me! - return KeepUtil.getCombinedBlockLevelKeepStrength( - getTableAndCaptionFO().getKeepWithPrevious()); - */ + public boolean getGeneratesBlockArea() { + return true; } + public boolean isRestartable() { + return true; + } } 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 a89519425..fc19f6d87 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 @@ -19,142 +19,265 @@ package org.apache.fop.layoutmgr.table; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; +import org.apache.fop.area.LineArea; +import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.table.TableCaption; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; -import org.apache.fop.layoutmgr.Keep; +import org.apache.fop.layoutmgr.BreakOpportunity; +import org.apache.fop.layoutmgr.KnuthElement; +import org.apache.fop.layoutmgr.KnuthPossPosIter; +import org.apache.fop.layoutmgr.LMiter; import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.ListElement; +import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.TraitSetter; +import org.apache.fop.traits.MinOptMax; /** * LayoutManager for a table-caption FO. - * The table caption contains blocks that are placed beside the - * table. + * A table caption consists of a table caption. + * The caption contains blocks that are positioned next to the + * table on the caption side. + * The caption blocks have an implicit keep with the table. * TODO Implement getNextKnuthElements() */ -public class TableCaptionLayoutManager extends BlockStackingLayoutManager { - +public class TableCaptionLayoutManager extends BlockStackingLayoutManager implements BreakOpportunity { private Block curBlockArea; + /** Iterator over the child layout managers. */ + private ProxyLMiter proxyLMiter; + /** - * Create a new Caption layout manager. - * @param node table-caption FO + * Create a new table caption layout manager. + * @param tableCaption the block FO object to create the layout manager for. */ - public TableCaptionLayoutManager(TableCaption node) { - super(node); + public TableCaptionLayoutManager(TableCaption tableCaption) { + super(tableCaption); + proxyLMiter = new ProxyLMiter(); } - /** @return the table-caption FO */ - public TableCaption getTableCaptionFO() { - return (TableCaption)this.fobj; + public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) { + return getNextKnuthElements(context, alignment, null, null, null); } /** - * Get the next break position for the caption. - * - * @param context the layout context for finding breaks - * @return the next break possibility + * Proxy iterator for Block LM. + * This iterator creates and holds the complete list + * of child LMs. + * It uses fobjIter as its base iterator. + * Block LM's createNextChildLMs uses this iterator + * as its base iterator. */ - /* - public BreakPoss getNextBreakPoss(LayoutContext context) { - LayoutManager curLM; // currently active LM - - MinOptMax stackSize = new MinOptMax(); - // if starting add space before - // stackSize.add(spaceBefore); - BreakPoss lastPos = null; - - // if there is a caption then get the side and work out when - // to handle it - - while ((curLM = getChildLM()) != null) { - // Make break positions and return blocks! - // Set up a LayoutContext - int ipd = context.getRefIPD(); - BreakPoss bp; - - LayoutContext childLC = LayoutContext.newInstance(); - // if line layout manager then set stack limit to ipd - // line LM actually generates a LineArea which is a block - childLC.setStackLimit( - MinOptMax.subtract(context.getStackLimit(), - stackSize)); - childLC.setRefIPD(ipd); - - boolean over = false; - - while (!curLM.isFinished()) { - if ((bp = curLM.getNextBreakPoss(childLC)) != null) { - if (stackSize.opt + bp.getStackingSize().opt > context.getStackLimit().max) { - // reset to last break - if (lastPos != null) { - LayoutManager lm = lastPos.getLayoutManager(); - lm.resetPosition(lastPos.getPosition()); - if (lm != curLM) { - curLM.resetPosition(null); - } - } else { - curLM.resetPosition(null); - } - over = true; - break; - } - stackSize.add(bp.getStackingSize()); - lastPos = bp; - childBreaks.add(bp); - - if (bp.nextBreakOverflows()) { - over = true; - break; - } - - childLC.setStackLimit(MinOptMax.subtract( - context.getStackLimit(), stackSize)); - } + protected class ProxyLMiter extends LMiter { + + /** + * Constructs a proxy iterator for Block LM. + */ + public ProxyLMiter() { + super(TableCaptionLayoutManager.this); + listLMs = new ArrayList<>(10); + } + + /** + * @return true if there are more child lms + */ + public boolean hasNext() { + return (curPos < listLMs.size()) || createNextChildLMs(curPos); + } + + /** + * @param pos ... + * @return true if new child lms were added + */ + protected boolean createNextChildLMs(int pos) { + List<LayoutManager> newLMs = createChildLMs(pos + 1 - listLMs.size()); + if (newLMs != null) { + listLMs.addAll(newLMs); } - BreakPoss breakPoss = new BreakPoss( - new LeafPosition(this, childBreaks.size() - 1)); - if (over) { - breakPoss.setFlag(BreakPoss.NEXT_OVERFLOWS, true); + return pos < listLMs.size(); + } + } + + public boolean createNextChildLMs(int pos) { + while (proxyLMiter.hasNext()) { + LayoutManager lm = proxyLMiter.next(); + addChildLM(lm); + if (pos < childLMs.size()) { + return true; } - breakPoss.setStackingSize(stackSize); - return breakPoss; } - setFinished(true); - return null; - }*/ + return false; + } - /** - * Add the areas to the parent. - * - * @param parentIter the position iterator of the breaks - * @param layoutContext the layout context for adding areas - */ - public void addAreas(PositionIterator parentIter, - LayoutContext layoutContext) { + public KeepProperty getKeepTogetherProperty() { + return getTableCaptionFO().getKeepTogether(); + } + + public KeepProperty getKeepWithPreviousProperty() { + return getTableCaptionFO().getKeepWithPrevious(); + } + + public KeepProperty getKeepWithNextProperty() { + return getTableCaptionFO().getKeepWithNext(); + } + + public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - addId(); - /* TODO: Reimplement using Knuth approach + // if this will create the first block area in a page + // and display-align is after or center, add space before + if (layoutContext.getSpaceBefore() > 0) { + addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore())); + } + LayoutManager childLM; - int iStartPos = 0; - LayoutContext lc = LayoutContext.newInstance(); + LayoutManager lastLM = null; + LayoutContext lc = LayoutContext.offspringOf(layoutContext); + lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); + // set space after in the LayoutContext for children + if (layoutContext.getSpaceAfter() > 0) { + lc.setSpaceAfter(layoutContext.getSpaceAfter()); + } + PositionIterator childPosIter; + + // "unwrap" the NonLeafPositions stored in parentIter + // and put them in a new list; + LinkedList<Position> positionList = new LinkedList<>(); + Position pos; + boolean spaceBefore = false; + boolean spaceAfter = false; + Position firstPos = null; + Position lastPos = null; while (parentIter.hasNext()) { - LeafPosition lfp = (LeafPosition) parentIter.next(); - // Add the block areas to Area - PositionIterator breakPosIter = new BreakPossPosIter( - childBreaks, iStartPos, lfp.getLeafPos() + 1); - iStartPos = lfp.getLeafPos() + 1; - while ((childLM = breakPosIter.getNextChildLM()) != null) { - childLM.addAreas(breakPosIter, lc); + pos = parentIter.next(); + if (pos.getIndex() >= 0) { + if (firstPos == null) { + firstPos = pos; + } + lastPos = pos; + } + Position innerPosition = pos; + if (pos instanceof NonLeafPosition) { + //Not all elements are wrapped + innerPosition = pos.getPosition(); + } + if (innerPosition == null) { + // pos was created by this BlockLM and was inside an element + // representing space before or after + // this means the space was not discarded + if (positionList.isEmpty()) { + // pos was in the element representing space-before + spaceBefore = true; + } else { + // pos was in the element representing space-after + spaceAfter = true; + } + } else if (innerPosition.getLM() == this + && !(innerPosition instanceof MappingPosition)) { + // pos was created by this BlockLM and was inside a penalty + // allowing or forbidding a page break + // nothing to do + } else { + // innerPosition was created by another LM + positionList.add(innerPosition); + lastLM = innerPosition.getLM(); + } + } + + addId(); + + registerMarkers(true, isFirst(firstPos), isLast(lastPos)); + + if (bpUnit == 0) { + // the Positions in positionList were inside the elements + // created by the LineLM + childPosIter = new StackingIter(positionList.listIterator()); + } else { + // the Positions in positionList were inside the elements + // created by the BlockLM in the createUnitElements() method + LinkedList<KnuthElement> splitList = new LinkedList<>(); + int splitLength = 0; + int iFirst = ((MappingPosition) positionList.getFirst()).getFirstIndex(); + int iLast = ((MappingPosition) positionList.getLast()).getLastIndex(); + // copy from storedList to splitList all the elements from + // iFirst to iLast + ListIterator<KnuthElement> storedListIterator = storedList.listIterator(iFirst); + while (storedListIterator.nextIndex() <= iLast) { + KnuthElement element = storedListIterator.next(); + // some elements in storedList (i.e. penalty items) were created + // by this BlockLM, and must be ignored + if (element.getLayoutManager() != this) { + splitList.add(element); + splitLength += element.getWidth(); + lastLM = element.getLayoutManager(); + } + } + // add space before and / or after the paragraph + // to reach a multiple of bpUnit + if (spaceBefore && spaceAfter) { + adjustedSpaceBefore = (neededUnits(splitLength + + foSpaceBefore.getMin() + + foSpaceAfter.getMin()) + * bpUnit - splitLength) / 2; + adjustedSpaceAfter = neededUnits(splitLength + + foSpaceBefore.getMin() + + foSpaceAfter.getMin()) + * bpUnit - splitLength - adjustedSpaceBefore; + } else if (spaceBefore) { + adjustedSpaceBefore = neededUnits(splitLength + + foSpaceBefore.getMin()) + * bpUnit - splitLength; + } else { + adjustedSpaceAfter = neededUnits(splitLength + + foSpaceAfter.getMin()) + * bpUnit - splitLength; } - }*/ + childPosIter = new KnuthPossPosIter(splitList, 0, splitList + .size()); + } + + while ((childLM = childPosIter.getNextChildLM()) != null) { + // set last area flag + lc.setFlags(LayoutContext.LAST_AREA, + (layoutContext.isLastArea() && childLM == lastLM)); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); + // Add the line areas to Area + childLM.addAreas(childPosIter, lc); + } + registerMarkers(false, isFirst(firstPos), isLast(lastPos)); flush(); - //childBreaks.clear(); curBlockArea = null; + + //Notify end of block layout manager to the PSLM + checkEndOfLayout(lastPos); + } + + private static class StackingIter extends PositionIterator { + public StackingIter(Iterator parentIter) { + super(parentIter); + } + + protected LayoutManager getLM(Object nextObj) { + return ((Position) nextObj).getLM(); + } + + protected Position getPos(Object nextObj) { + return ((Position) nextObj); + } } /** @@ -166,55 +289,77 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { * Finally, based on the dimensions of the parent area, it initializes * its own area. This includes setting the content IPD and the maximum * BPD. - * - * @param childArea the child area - * @return the parent area from this caption + * @param childArea area to get the parent area for + * @return the parent area */ public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); - curBlockArea.setChangeBarList(getChangeBarList()); - // Set up dimensions + curBlockArea.setIPD(super.getContentAreaIPD()); + + curBlockArea.setBidiLevel(getTableCaptionFO().getBidiLevelRecursive()); + // Must get dimensions from parent area - Area parentArea = parentLayoutManager.getParentArea(curBlockArea); - int referenceIPD = parentArea.getIPD(); - curBlockArea.setIPD(referenceIPD); - curBlockArea.setBidiLevel(getTableCaptionFO().getBidiLevel()); - // Get reference IPD from parentArea + //Don't optimize this line away. It can have ugly side-effects. + parentLayoutManager.getParentArea(curBlockArea); + + // set traits + TraitSetter.setProducerID(curBlockArea, getTableCaptionFO().getId()); + TraitSetter.setLayer(curBlockArea, getTableCaptionFO().getLayer()); + curBlockArea.setLocation(FONode.getLocatorString(getTableCaptionFO().getLocator())); setCurrentArea(curBlockArea); // ??? for generic operations } return curBlockArea; } - /** - * Add the child to the caption area. - * - * @param childArea the child area to add - */ public void addChildArea(Area childArea) { if (curBlockArea != null) { + if (childArea instanceof LineArea) { + curBlockArea.addLineArea((LineArea) childArea); + } else { curBlockArea.addBlock((Block) childArea); + } } } - /** {@inheritDoc} */ - public Keep getKeepWithNext() { - return Keep.KEEP_AUTO; - /* TODO Complete me! - return KeepUtil.getCombinedBlockLevelKeepStrength( - getTableCaptionFO().getKeepWithNext()); - */ + /** + * Returns the table-caption formatting object. + * @return the table-caption formatting object + */ + protected TableCaption getTableCaptionFO() { + return (TableCaption) fobj; } - /** {@inheritDoc} */ - public Keep getKeepWithPrevious() { - return Keep.KEEP_AUTO; - /* TODO Complete me! - return KeepUtil.getCombinedBlockLevelKeepStrength( - getTableCaptionFO().getKeepWithPrevious()); - */ + // --------- Property Resolution related functions --------- // + + /** + * Returns the IPD of the content area + * @return the IPD of the content area + */ + public int getContentAreaIPD() { + if (curBlockArea != null) { + return curBlockArea.getIPD(); + } + return super.getContentAreaIPD(); } -} + /** + * Returns the BPD of the content area + * @return the BPD of the content area + */ + public int getContentAreaBPD() { + if (curBlockArea != null) { + return curBlockArea.getBPD(); + } + return -1; + } + public boolean getGeneratesBlockArea() { + return true; + } + + public boolean isRestartable() { + return true; + } +} diff --git a/fop-core/src/test/java/org/apache/fop/fo/flow/table/UnimplementedWarningNeutralizer.java b/fop-core/src/test/java/org/apache/fop/fo/flow/table/UnimplementedWarningNeutralizer.java deleted file mode 100644 index 1a5e38291..000000000 --- a/fop-core/src/test/java/org/apache/fop/fo/flow/table/UnimplementedWarningNeutralizer.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.table; - -/** - * This class aims at easing testing, by preventing the event notification system from - * getting in the way just to issue an Unimplemented Feature warning. - */ -public final class UnimplementedWarningNeutralizer { - - private UnimplementedWarningNeutralizer() { } - - /** - * Neutralizes Unimplemented Feature events from the {@link TableAndCaption} and - * {@link TableCaption} classes. - */ - public static void neutralizeUnimplementedWarning() { - TableAndCaption.notImplementedWarningGiven = true; - TableCaption.notImplementedWarningGiven = true; - } -} diff --git a/fop-core/src/test/java/org/apache/fop/fo/properties/CommonAccessibilityHolderTestCase.java b/fop-core/src/test/java/org/apache/fop/fo/properties/CommonAccessibilityHolderTestCase.java index 81ebc2f41..008ab0580 100644 --- a/fop-core/src/test/java/org/apache/fop/fo/properties/CommonAccessibilityHolderTestCase.java +++ b/fop-core/src/test/java/org/apache/fop/fo/properties/CommonAccessibilityHolderTestCase.java @@ -34,7 +34,6 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FONodeMocks; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; -import org.apache.fop.fo.flow.table.UnimplementedWarningNeutralizer; /** * This tests that all the FONodes that implement CommonAccessibilityHolder correctly configure @@ -50,10 +49,6 @@ public class CommonAccessibilityHolderTestCase { private final String sourceDocument = "source document"; static { - /* This triggers 'unimplemented feature' FO validation events so that the event system is - * not triggered when testing, avoiding extra convoluted dependency stubbing. */ - UnimplementedWarningNeutralizer.neutralizeUnimplementedWarning(); - IMPLEMENTATIONS.add(org.apache.fop.fo.flow.BasicLink.class); IMPLEMENTATIONS.add(org.apache.fop.fo.flow.Block.class); IMPLEMENTATIONS.add(org.apache.fop.fo.pagination.bookmarks.Bookmark.class); diff --git a/fop/test/layoutengine/standard-testcases/table_and_caption.xml b/fop/test/layoutengine/standard-testcases/table_and_caption.xml new file mode 100644 index 000000000..e5bdf1e50 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/table_and_caption.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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$ --> +<testcase> + <info> + <p> + This test checks table with a caption + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="simple" page-height="27.9cm" page-width="21.6cm"> + <fo:region-body margin="1cm"/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="simple"> + <fo:flow flow-name="xsl-region-body"> + <fo:table-and-caption border="solid 0.5mm black"> + <fo:table-caption> + <fo:block text-align="center">test</fo:block> + </fo:table-caption> + <fo:table table-layout="fixed" width="100%"> + <fo:table-column column-width="proportional-column-width(50)"/> + <fo:table-column column-width="proportional-column-width(50)"/> + <fo:table-header> + <fo:table-row> + <fo:table-cell> + <fo:block>header1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>header2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-header> + <fo:table-body> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + </fo:table-and-caption> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="test" xpath="//block/block[1]//word"/> + <eval expected="header1" xpath="//block/block[2]/block[1]/block//word"/> + <eval expected="header2" xpath="//block/block[2]/block[2]/block//word"/> + <eval expected="cell1" xpath="//block/block[2]/block[3]/block//word"/> + <eval expected="cell2" xpath="//block/block[2]/block[4]/block//word"/> + <eval expected="(solid,#000000,1417)" xpath="//block/@border-start"/> + </checks> +</testcase> diff --git a/fop/test/layoutengine/standard-testcases/table_and_caption_multicolumn.xml b/fop/test/layoutengine/standard-testcases/table_and_caption_multicolumn.xml new file mode 100644 index 000000000..fecebe494 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/table_and_caption_multicolumn.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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$ --> +<testcase> + <info> + <p> + This test checks table with a caption + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"> + <fo:layout-master-set> + <fo:simple-page-master master-name="simple" page-height="10cm" page-width="21.6cm"> + <fo:region-body margin="1cm" column-count="2"/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="simple"> + <fo:flow flow-name="xsl-region-body"> + <fo:block font-size="40pt">test test test test test test test test test test test test </fo:block> + <fo:table-and-caption border="solid 0.5mm black" font-size="35pt"> + <fo:table-caption> + <fo:block text-align="center">caption</fo:block> + </fo:table-caption> + <fo:table table-layout="fixed" width="100%"> + <fo:table-column column-width="proportional-column-width(50)"/> + <fo:table-column column-width="proportional-column-width(50)"/> + <fo:table-header> + <fo:table-row> + <fo:table-cell> + <fo:block>header1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>header2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-header> + <fo:table-body> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + </fo:table-and-caption> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="2" xpath="count(//pageViewport)"/> + <eval expected="test" xpath="//pageViewport[1]//flow[1]//word"/> + <eval expected="caption" xpath="//pageViewport[1]//flow[2]//word"/> + <eval expected="header1" xpath="//pageViewport[2]//word"/> + </checks> +</testcase> diff --git a/fop/test/layoutengine/standard-testcases/table_and_caption_multipage.xml b/fop/test/layoutengine/standard-testcases/table_and_caption_multipage.xml new file mode 100644 index 000000000..c4552bcc6 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/table_and_caption_multipage.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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$ --> +<testcase> + <info> + <p> + This test checks table with a caption + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"> + <fo:layout-master-set> + <fo:simple-page-master master-name="simple" page-height="10cm" page-width="21.6cm"> + <fo:region-body margin="1cm"/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="simple"> + <fo:flow flow-name="xsl-region-body"> + <fo:block font-size="40pt">test test test test test test test test test test test test </fo:block> + <fo:table-and-caption border="solid 0.5mm black" font-size="40pt"> + <fo:table-caption> + <fo:block text-align="center">caption</fo:block> + </fo:table-caption> + <fo:table table-layout="fixed" width="100%"> + <fo:table-column column-width="proportional-column-width(50)"/> + <fo:table-column column-width="proportional-column-width(50)"/> + <fo:table-header> + <fo:table-row> + <fo:table-cell> + <fo:block>header1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>header2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-header> + <fo:table-body> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + </fo:table-and-caption> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="3" xpath="count(//pageViewport)"/> + <eval expected="test" xpath="//pageViewport[1]//word"/> + <eval expected="caption" xpath="//pageViewport[2]//word"/> + <eval expected="header1" xpath="//pageViewport[3]//word"/> + </checks> +</testcase> |