Browse Source

Implemented limited support for extension properties through new methods on ElementMapping (backwards-compatible).

Moved block-progression-unit into the fox: namespace.
Implemented new extension properties: fox:orphan-content-limit and fox:widow-content-limit for fo:table and fo:list-block. See documentation for details.
Bugfix in ElementListUtils.removeLegalBreaks (concerning box/glue combinations). Added a unit test to cover the problem.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@442282 13f79535-47bb-0310-9956-ffa450edef68
pull/25/head
Jeremias Maerki 18 years ago
parent
commit
2dd52b5991
22 changed files with 1035 additions and 65 deletions
  1. 20
    2
      src/documentation/content/xdocs/trunk/extensions.xml
  2. 6
    2
      src/java/org/apache/fop/fo/Constants.java
  3. 16
    0
      src/java/org/apache/fop/fo/ElementMapping.java
  4. 10
    0
      src/java/org/apache/fop/fo/ElementMappingRegistry.java
  5. 12
    0
      src/java/org/apache/fop/fo/FOElementMapping.java
  6. 17
    5
      src/java/org/apache/fop/fo/FOPropertyMapping.java
  7. 5
    14
      src/java/org/apache/fop/fo/FObj.java
  8. 13
    2
      src/java/org/apache/fop/fo/PropertyList.java
  9. 25
    0
      src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
  10. 5
    0
      src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java
  11. 20
    6
      src/java/org/apache/fop/fo/flow/ListBlock.java
  12. 20
    6
      src/java/org/apache/fop/fo/flow/Table.java
  13. 78
    16
      src/java/org/apache/fop/layoutmgr/ElementListUtils.java
  14. 16
    10
      src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
  15. 12
    2
      src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
  16. 4
    0
      status.xml
  17. 147
    0
      test/java/org/apache/fop/util/ElementListUtilsTestCase.java
  18. 123
    0
      test/layoutengine/standard-testcases/list-block_fox_orphan-content-limit_1.xml
  19. 123
    0
      test/layoutengine/standard-testcases/list-block_fox_widow-content-limit_1.xml
  20. 133
    0
      test/layoutengine/standard-testcases/table_fox_orphan-content-limit_1.xml
  21. 133
    0
      test/layoutengine/standard-testcases/table_fox_widow-content-limit_1.xml
  22. 97
    0
      test/layoutengine/standard-testcases/table_fox_widow-content-limit_2.xml

+ 20
- 2
src/documentation/content/xdocs/trunk/extensions.xml View File

<code>http://xml.apache.org/fop/extensions</code> to the root element: <code>http://xml.apache.org/fop/extensions</code> to the root element:
</p> </p>
<source><![CDATA[<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" <source><![CDATA[<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fox="http://xml.apache.org/fop/extensions">]]></source>
<note>Currently, no extensions are implemented in FOP Trunk which use the FOP extension namespace.</note>
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">]]></source>
<note>
Currently, no extension elements are implemented in FOP Trunk which use the
FOP extension namespace.
</note>
</section> </section>
<section id="bookmarks"> <section id="bookmarks">
<title>PDF Bookmarks</title> <title>PDF Bookmarks</title>
</fo:table-row> </fo:table-row>
</fo:table-header>]]></source--> </fo:table-header>]]></source-->
</section> </section>
<section id="widow-orphan-content-limit">
<title>fox:orphan-content-limit and fox:widow-content-limit</title>
<p>
The two proprietary extension properties, fox:orphan-content-limit and
fox:widow-content-limit, are used to improve the layout of list-blocks and tables.
If you have a table with many entries, you don't want a single row to be left over
on a page. You will want to make sure that at least two or three lines are kept
together. The properties take an absolute length which specifies the area at the
beginning (fox:widow-content-limit) or at the end (fox:orphan-content-limit) of a
table or list-block. The properties are inherited and only have an effect on fo:table
and fo:list-block. An example: fox:widow-content-limit="3 * 1.2em" would make sure
the you'll have at least three lines (assuming line-height="1.2") together on a table
or list-block.
</p>
</section>
</section> </section>
</body> </body>
</document> </document>

+ 6
- 2
src/java/org/apache/fop/fo/Constants.java View File

int PR_INDEX_CLASS = 249; int PR_INDEX_CLASS = 249;
/** Property constant - XSL 1.1 */ /** Property constant - XSL 1.1 */
int PR_INDEX_KEY = 250; int PR_INDEX_KEY = 250;
/** Property constant - Custom extension */
/** Property constant - FOP proprietary: Custom extension for line alignment */
int PR_X_BLOCK_PROGRESSION_UNIT = 251; int PR_X_BLOCK_PROGRESSION_UNIT = 251;
/** Property constant - FOP proprietary: limit for widow content in lists and tables */
int PR_X_WIDOW_CONTENT_LIMIT = 252;
/** Property constant - FOP proprietary: limit for orphan content in lists and tables */
int PR_X_ORPHAN_CONTENT_LIMIT = 253;
/** Number of property constants defined */ /** Number of property constants defined */
int PROPERTY_COUNT = 251;
int PROPERTY_COUNT = 253;


// compound property constants // compound property constants



+ 16
- 0
src/java/org/apache/fop/fo/ElementMapping.java View File

import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;


import org.apache.fop.util.QName;
import org.w3c.dom.DOMImplementation; import org.w3c.dom.DOMImplementation;


/** /**
"Cannot return default DOM implementation: " + e.getMessage()); "Cannot return default DOM implementation: " + e.getMessage());
} }
} }

/** @return the standard namespace prefix for this namespace or null if it is not known. */
public String getStandardPrefix() {
return null;
}
/**
* Indicates whether a particular attribute of the namespace is a property, i.e. the attribute
* value should be converted to a property value.
* @param attributeName the attribute name
* @return true if the attribute should be converted to a property
*/
public boolean isAttributeProperty(QName attributeName) {
return false;
}
/** /**
* Initializes the set of maker objects associated with this ElementMapping * Initializes the set of maker objects associated with this ElementMapping

+ 10
- 0
src/java/org/apache/fop/fo/ElementMappingRegistry.java View File

} }
} }
/**
* Returns an ElementMapping class for a namespace URI if there is one.
* @param namespaceURI the namespace URI
* @return the requested ElementMapping or null, if no ElementMapping for the namespace is
* available.
*/
public ElementMapping getElementMapping(String namespaceURI) {
return (ElementMapping)this.namespaces.get(namespaceURI);
}
/** /**
* Indicates whether a namespace is known to FOP. * Indicates whether a namespace is known to FOP.
* @param namespaceURI the namespace URI * @param namespaceURI the namespace URI

+ 12
- 0
src/java/org/apache/fop/fo/FOElementMapping.java View File

// Java // Java
import java.util.HashMap; import java.util.HashMap;


import org.apache.fop.util.QName;

/** /**
* Element mapping class for all XSL-FO elements. * Element mapping class for all XSL-FO elements.
*/ */
} }
} }


/** @see org.apache.fop.fo.ElementMapping#getStandardPrefix() */
public String getStandardPrefix() {
return "fo";
}
/** @see org.apache.fop.fo.ElementMapping#isAttributeProperty(org.apache.fop.util.QName) */
public boolean isAttributeProperty(QName attributeName) {
return true; //All XSL-FO attributes are to be converted to properties.
}
static class RootMaker extends ElementMapping.Maker { static class RootMaker extends ElementMapping.Maker {
public FONode make(FONode parent) { public FONode make(FONode parent) {
return new org.apache.fop.fo.pagination.Root(parent); return new org.apache.fop.fo.pagination.Root(parent);

+ 17
- 5
src/java/org/apache/fop/fo/FOPropertyMapping.java View File

l.setDefault("auto"); l.setDefault("auto");
addPropertyMaker("width", l); addPropertyMaker("width", l);


/*LF*/ // block-progression-unit (**CUSTOM EXTENSION**)
/*LF*/ l = new LengthProperty.Maker(PR_X_BLOCK_PROGRESSION_UNIT);
/*LF*/ l.setInherited(false);
/*LF*/ l.setDefault("0pt");
/*LF*/ addPropertyMaker("block-progression-unit", l);
// fox:block-progression-unit (**CUSTOM EXTENSION**)
l = new LengthProperty.Maker(PR_X_BLOCK_PROGRESSION_UNIT);
l.setInherited(false);
l.setDefault("0pt");
addPropertyMaker("fox:block-progression-unit", l);
} }


private void createBlockAndLineProperties() { private void createBlockAndLineProperties() {
m.setInherited(true); m.setInherited(true);
m.setDefault("2"); m.setDefault("2");
addPropertyMaker("widows", m); addPropertyMaker("widows", m);
// fox:widow-content-limit
m = new LengthProperty.Maker(PR_X_WIDOW_CONTENT_LIMIT);
m.setInherited(true);
m.setDefault("0pt");
addPropertyMaker("fox:widow-content-limit", m);

// fox:orphan-content-limit
m = new LengthProperty.Maker(PR_X_ORPHAN_CONTENT_LIMIT);
m.setInherited(true);
m.setDefault("0pt");
addPropertyMaker("fox:orphan-content-limit", m);
} }


private void createLayoutProperties() { private void createLayoutProperties() {

+ 5
- 14
src/java/org/apache/fop/fo/FObj.java View File



/** /**
* Adds a foreign attribute to this FObj. * Adds a foreign attribute to this FObj.
* @param uri the namespace URI
* @param qName the fully qualified name
* @param attributeName the attribute name as a QName instance
* @param value the attribute value * @param value the attribute value
*/ */
public void addForeignAttribute(String uri,
String qName, String value) {
public void addForeignAttribute(QName attributeName, String value) {
/* TODO: Handle this over FOP's property mechanism so we can use /* TODO: Handle this over FOP's property mechanism so we can use
* inheritance. * inheritance.
*/ */
if (qName == null) {
throw new NullPointerException("Parameter qName must not be null");
if (attributeName == null) {
throw new NullPointerException("Parameter attributeName must not be null");
} }
if (foreignAttributes == null) { if (foreignAttributes == null) {
foreignAttributes = new java.util.HashMap(); foreignAttributes = new java.util.HashMap();
} }
String localName = qName;
String prefix = null;
int p = localName.indexOf(':');
if (p > 0) {
prefix = localName.substring(0, p);
localName = localName.substring(p + 1);
}
foreignAttributes.put(new QName(uri, prefix, localName), value);
foreignAttributes.put(attributeName, value);
} }
/** @return the map of foreign attributes */ /** @return the map of foreign attributes */

+ 13
- 2
src/java/org/apache/fop/fo/PropertyList.java View File

import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.CommonTextDecoration;
import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.PropertyMaker; import org.apache.fop.fo.properties.PropertyMaker;
import org.apache.fop.util.QName;


/** /**
* Class containing the collection of properties for a given FObj. * Class containing the collection of properties for a given FObj.
if (attributeNS == null || attributeNS.length() == 0) { if (attributeNS == null || attributeNS.length() == 0) {
convertAttributeToProperty(attributes, attributeName, attributeValue); convertAttributeToProperty(attributes, attributeName, attributeValue);
} else if (!factory.isNamespaceIgnored(attributeNS)) { } else if (!factory.isNamespaceIgnored(attributeNS)) {
if (factory.getElementMappingRegistry().isKnownNamespace(attributeNS)) {
getFObj().addForeignAttribute(attributeNS, attributeName, attributeValue);
ElementMapping mapping = factory.getElementMappingRegistry().getElementMapping(
attributeNS);
if (mapping != null) {
QName attName = new QName(attributeNS, attributeName);
if (mapping.isAttributeProperty(attName)
&& mapping.getStandardPrefix() != null) {
convertAttributeToProperty(attributes,
mapping.getStandardPrefix() + ":" + attName.getLocalName(),
attributeValue);
} else {
getFObj().addForeignAttribute(attName, attributeValue);
}
} else { } else {
handleInvalidProperty( handleInvalidProperty(
"Error processing foreign attribute: " "Error processing foreign attribute: "

+ 25
- 0
src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java View File



import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.UnknownXMLObj; import org.apache.fop.fo.UnknownXMLObj;
import org.apache.fop.util.QName;


import java.util.HashMap; import java.util.HashMap;
import java.util.Set;


/** /**
* Element mapping for FOP's proprietary extension to XSL-FO. * Element mapping for FOP's proprietary extension to XSL-FO.
/** The FOP extension namespace URI */ /** The FOP extension namespace URI */
public static final String URI = "http://xmlgraphics.apache.org/fop/extensions"; public static final String URI = "http://xmlgraphics.apache.org/fop/extensions";


private static final Set propertyAttributes = new java.util.HashSet();
static {
//These are FOP's standard extension properties (fox:*)
propertyAttributes.add("block-progression-unit");
propertyAttributes.add("widow-content-limit");
propertyAttributes.add("orphan-content-limit");
}
/** /**
* Constructor. * Constructor.
*/ */
foObjs.put("label", new UnknownXMLObj.Maker(URI)); foObjs.put("label", new UnknownXMLObj.Maker(URI));
} }
} }
/** @see org.apache.fop.fo.ElementMapping#getStandardPrefix() */
public String getStandardPrefix() {
return "fox";
}
/** @see org.apache.fop.fo.ElementMapping#isAttributeProperty(org.apache.fop.util.QName) */
public boolean isAttributeProperty(QName attributeName) {
if (!URI.equals(attributeName.getNamespaceURI())) {
throw new IllegalArgumentException("The namespace URIs don't match");
}
return propertyAttributes.contains(attributeName.getLocalName());
}
} }

+ 5
- 0
src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java View File

} }
} }


/** @see org.apache.fop.fo.ElementMapping#getStandardPrefix() */
public String getStandardPrefix() {
return "svg";
}

static class SVGMaker extends ElementMapping.Maker { static class SVGMaker extends ElementMapping.Maker {
public FONode make(FONode parent) { public FONode make(FONode parent) {
return new SVGObj(parent); return new SVGObj(parent);

+ 20
- 6
src/java/org/apache/fop/fo/flow/ListBlock.java View File

private Length provisionalLabelSeparation; private Length provisionalLabelSeparation;
// End of property values // End of property values


/** extension properties */
private Length widowContentLimit;
private Length orphanContentLimit;
// used for child node validation // used for child node validation
private boolean hasListItem = false; private boolean hasListItem = false;


PR_PROVISIONAL_DISTANCE_BETWEEN_STARTS).getLength(); PR_PROVISIONAL_DISTANCE_BETWEEN_STARTS).getLength();
provisionalLabelSeparation = pList.get( provisionalLabelSeparation = pList.get(
PR_PROVISIONAL_LABEL_SEPARATION).getLength(); PR_PROVISIONAL_LABEL_SEPARATION).getLength();

//Bind extension properties
widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength();
orphanContentLimit = pList.get(PR_X_ORPHAN_CONTENT_LIMIT).getLength();
} }


/** /**
return keepTogether; return keepTogether;
} }


/**
* @return the "id" property.
*/
/** @return the "fox:widow-content-limit" extension property */
public Length getWidowContentLimit() {
return widowContentLimit;
}

/** @return the "fox:orphan-content-limit" extension property */
public Length getOrphanContentLimit() {
return orphanContentLimit;
}

/** @return the "id" property. */
public String getId() { public String getId() {
return id; return id;
} }
return "list-block"; return "list-block";
} }
/**
* @see org.apache.fop.fo.FObj#getNameId()
*/
/** @see org.apache.fop.fo.FObj#getNameId() */
public int getNameId() { public int getNameId() {
return FO_LIST_BLOCK; return FO_LIST_BLOCK;
} }

+ 20
- 6
src/java/org/apache/fop/fo/flow/Table.java View File

private int tableOmitFooterAtBreak; private int tableOmitFooterAtBreak;
private int tableOmitHeaderAtBreak; private int tableOmitHeaderAtBreak;
private int writingMode; private int writingMode;
/** extension properties */
private Length widowContentLimit;
private Length orphanContentLimit;


private static final int MINCOLWIDTH = 10000; // 10pt private static final int MINCOLWIDTH = 10000; // 10pt


tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum(); tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum();
writingMode = pList.get(PR_WRITING_MODE).getEnum(); writingMode = pList.get(PR_WRITING_MODE).getEnum();
super.bind(pList); super.bind(pList);

//Bind extension properties
widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength();
orphanContentLimit = pList.get(PR_X_ORPHAN_CONTENT_LIMIT).getLength();
if (borderCollapse != EN_SEPARATE) { if (borderCollapse != EN_SEPARATE) {
//TODO Remove once the collapsing border is at least marginally working. //TODO Remove once the collapsing border is at least marginally working.
public LengthPairProperty getBorderSeparation() { public LengthPairProperty getBorderSeparation() {
return borderSeparation; return borderSeparation;
} }
/** @return the "fox:widow-content-limit" extension property */
public Length getWidowContentLimit() {
return widowContentLimit;
}


/**
* @return the "id" property.
*/
/** @return the "fox:orphan-content-limit" extension property */
public Length getOrphanContentLimit() {
return orphanContentLimit;
}

/** @return the "id" property. */
public String getId() { public String getId() {
return id; return id;
} }
return "table"; return "table";
} }


/**
* @see org.apache.fop.fo.FObj#getNameId()
*/
/** @see org.apache.fop.fo.FObj#getNameId() */
public int getNameId() { public int getNameId() {
return FO_TABLE; return FO_TABLE;
} }

+ 78
- 16
src/java/org/apache/fop/layoutmgr/ElementListUtils.java View File

//Convert all penalties no break inhibitors //Convert all penalties no break inhibitors
if (breakPoss.getPenaltyValue() < KnuthPenalty.INFINITE) { if (breakPoss.getPenaltyValue() < KnuthPenalty.INFINITE) {
breakPoss.setPenaltyValue(KnuthPenalty.INFINITE); breakPoss.setPenaltyValue(KnuthPenalty.INFINITE);
/*
i.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE,
penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary()));
*/
} }
} else if (el.isGlue()) { } else if (el.isGlue()) {
i.previous(); i.previous();
if (el.isBox()) { if (el.isBox()) {
i.next(); i.next();
i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false,
/*new Position(getTableLM())*/null, false));
null, false));
} }
} }
} }
} }
/** /**
* Removes all legal breaks in an element list. A constraint can be specified to limit the
* Removes legal breaks in an element list. A constraint can be specified to limit the
* range in which the breaks are removed. Legal breaks occuring before at least * range in which the breaks are removed. Legal breaks occuring before at least
* constraint.opt space is filled will be removed. * constraint.opt space is filled will be removed.
* @param elements the element list * @param elements the element list
* @return true if the opt constraint is bigger than the list contents * @return true if the opt constraint is bigger than the list contents
*/ */
public static boolean removeLegalBreaks(LinkedList elements, MinOptMax constraint) { public static boolean removeLegalBreaks(LinkedList elements, MinOptMax constraint) {
return removeLegalBreaks(elements, constraint.opt);
}
/**
* Removes legal breaks in an element list. A constraint can be specified to limit the
* range in which the breaks are removed. Legal breaks occuring before at least
* constraint space is filled will be removed.
* @param elements the element list
* @param constraint value to restrict the range in which the breaks are removed.
* @return true if the constraint is bigger than the list contents
*/
public static boolean removeLegalBreaks(LinkedList elements, int constraint) {
int len = 0; int len = 0;
ListIterator i = elements.listIterator();
while (i.hasNext()) {
KnuthElement el = (KnuthElement)i.next();
ListIterator iter = elements.listIterator();
while (iter.hasNext()) {
ListElement el = (ListElement)iter.next();
if (el.isPenalty()) { if (el.isPenalty()) {
KnuthPenalty penalty = (KnuthPenalty)el; KnuthPenalty penalty = (KnuthPenalty)el;
//Convert all penalties no break inhibitors
//Convert all penalties to break inhibitors
if (penalty.getP() < KnuthPenalty.INFINITE) {
iter.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE,
penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary()));
}
} else if (el.isGlue()) {
KnuthGlue glue = (KnuthGlue)el;
len += glue.getW();
iter.previous();
el = (ListElement)iter.previous();
iter.next();
if (el.isBox()) {
iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false,
null, false));
}
iter.next();
} else if (el instanceof BreakElement) {
BreakElement breakEl = (BreakElement)el;
if (breakEl.getPenaltyValue() < KnuthPenalty.INFINITE) {
breakEl.setPenaltyValue(KnuthPenalty.INFINITE);
}
} else {
KnuthElement kel = (KnuthElement)el;
len += kel.getW();
}
if (len >= constraint) {
return false;
}
}
return true;
}

/**
* Removes legal breaks in an element list. A constraint can be specified to limit the
* range in which the breaks are removed. Legal breaks within the space specified through the
* constraint (starting from the end of the element list) will be removed.
* @param elements the element list
* @param constraint value to restrict the range in which the breaks are removed.
* @return true if the constraint is bigger than the list contents
*/
public static boolean removeLegalBreaksFromEnd(LinkedList elements, int constraint) {
int len = 0;
ListIterator i = elements.listIterator(elements.size());
while (i.hasPrevious()) {
ListElement el = (ListElement)i.previous();
if (el.isPenalty()) {
KnuthPenalty penalty = (KnuthPenalty)el;
//Convert all penalties to break inhibitors
if (penalty.getP() < KnuthPenalty.INFINITE) { if (penalty.getP() < KnuthPenalty.INFINITE) {
i.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, i.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE,
penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary())); penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary()));
} }
} else if (el.isGlue()) { } else if (el.isGlue()) {
len += el.getW();
i.previous();
KnuthGlue glue = (KnuthGlue)el;
len += glue.getW();
el = (ListElement)i.previous();
i.next();
if (el.isBox()) { if (el.isBox()) {
i.next();
i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false,
/*new Position(getTableLM())*/null, false));
null, false));
}
} else if (el instanceof BreakElement) {
BreakElement breakEl = (BreakElement)el;
if (breakEl.getPenaltyValue() < KnuthPenalty.INFINITE) {
breakEl.setPenaltyValue(KnuthPenalty.INFINITE);
} }
} else { } else {
len += el.getW();
KnuthElement kel = (KnuthElement)el;
len += kel.getW();
} }
if (len > constraint.opt) {
if (len >= constraint) {
return false; return false;
} }
} }

+ 16
- 10
src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java View File

import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.PositionIterator;
} }
} }


/*
private class SectionPosition extends LeafPosition {
protected List list;
protected SectionPosition(LayoutManager lm, int pos, List l) {
super(lm, pos);
list = l;
}
}*/

/** /**
* Create a new list block layout manager. * Create a new list block layout manager.
* @param node list-block to create the layout manager for * @param node list-block to create the layout manager for
/** @see org.apache.fop.layoutmgr.BlockStackingLayoutManager */ /** @see org.apache.fop.layoutmgr.BlockStackingLayoutManager */
public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
resetSpaces(); resetSpaces();
return super.getNextKnuthElements(context, alignment);
LinkedList returnList = super.getNextKnuthElements(context, alignment);

//fox:widow-content-limit
int widowRowLimit = getListBlockFO().getWidowContentLimit().getValue();
if (widowRowLimit != 0) {
ElementListUtils.removeLegalBreaks(returnList, widowRowLimit);
}

//fox:orphan-content-limit
int orphanRowLimit = getListBlockFO().getOrphanContentLimit().getValue();
if (orphanRowLimit != 0) {
ElementListUtils.removeLegalBreaksFromEnd(returnList, orphanRowLimit);
}

return returnList;
} }
/** @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(java.util.List, int) */ /** @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(java.util.List, int) */

+ 12
- 2
src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java View File

} }
} else { } else {
if (!firstBreakBeforeServed) { if (!firstBreakBeforeServed) {
//returnList.add(new KnuthPenalty(0, -KnuthPenalty.INFINITE,
// false, rowFO.getBreakBefore(), new Position(getTableLM()), true));
returnList.add(new BreakElement(new Position(getTableLM()), returnList.add(new BreakElement(new Position(getTableLM()),
0, -KnuthPenalty.INFINITE, rowFO.getBreakBefore(), context)); 0, -KnuthPenalty.INFINITE, rowFO.getBreakBefore(), context));
iter.backToPreviousRow(); iter.backToPreviousRow();
} }
} }
} }

//fox:widow-content-limit
int widowContentLimit = getTableLM().getTable().getWidowContentLimit().getValue();
if (widowContentLimit != 0 && bodyType == TableRowIterator.BODY) {
ElementListUtils.removeLegalBreaks(returnList, widowContentLimit);
}
//fox:orphan-content-limit
int orphanContentLimit = getTableLM().getTable().getOrphanContentLimit().getValue();
if (orphanContentLimit != 0 && bodyType == TableRowIterator.BODY) {
ElementListUtils.removeLegalBreaksFromEnd(returnList, orphanContentLimit);
}
return returnList; return returnList;
} }



+ 4
- 0
status.xml View File



<changes> <changes>
<release version="FOP Trunk"> <release version="FOP Trunk">
<action context="Code" dev="JM" type="add">
Extension properties fox:orphan-content-limit and fox:widow-content-limit which
help with list-block and table layout. See the documentation for details.
</action>
<action context="Code" dev="JM" type="add"> <action context="Code" dev="JM" type="add">
Configuration option in the Java2D-based renderers that allows to disable the default Configuration option in the Java2D-based renderers that allows to disable the default
white background in order to produce bitmap output with transparency. white background in order to produce bitmap output with transparency.

+ 147
- 0
test/java/org/apache/fop/util/ElementListUtilsTestCase.java View File

/*
* 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.util;

import java.util.LinkedList;

import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.KnuthPenalty;

import junit.framework.TestCase;

/**
* Test class for ElementListUtils.
*/
public class ElementListUtilsTestCase extends TestCase {

/**
* Tests ElementListUtils.removeLegalBreaks().
* @throws Exception if the test fails
*/
public void testRemoveElementPenalty1() throws Exception {
LinkedList lst = new LinkedList();
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, 0, false, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, 200, false, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, 0, false, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, null, false));
lst.add(new KnuthGlue(0, Integer.MAX_VALUE, 0, null, false));
lst.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, null, false));
boolean res = ElementListUtils.removeLegalBreaks(lst, 9000);
assertFalse(res);

assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(1)).getP());
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getP());
assertEquals(0, ((KnuthPenalty)lst.get(5)).getP());
}
/**
* Tests ElementListUtils.removeLegalBreaks().
* @throws Exception if the test fails
*/
public void testRemoveElementPenalty2() throws Exception {
LinkedList lst = new LinkedList();
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthGlue(0, 0, 0, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthGlue(0, 0, 0, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthGlue(0, 0, 0, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, null, false));
lst.add(new KnuthGlue(0, Integer.MAX_VALUE, 0, null, false));
lst.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, null, false));
boolean res = ElementListUtils.removeLegalBreaks(lst, 9000);
assertFalse(res);
//Must insert an INFINITE penalty
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(1)).getP());
assertEquals(0, ((KnuthGlue)lst.get(2)).getW());
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(4)).getP());
assertEquals(0, ((KnuthGlue)lst.get(5)).getW());
assertEquals(0, ((KnuthGlue)lst.get(7)).getW());
}
/**
* Tests ElementListUtils.removeLegalBreaksFromEnd().
* @throws Exception if the test fails
*/
public void testRemoveElementFromEndPenalty1() throws Exception {
LinkedList lst = new LinkedList();
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, 0, false, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, 200, false, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, 0, false, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, null, false));
lst.add(new KnuthGlue(0, Integer.MAX_VALUE, 0, null, false));
lst.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, null, false));
boolean res = ElementListUtils.removeLegalBreaksFromEnd(lst, 9000);
assertFalse(res);

assertEquals(0, ((KnuthPenalty)lst.get(1)).getP());
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getP());
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(5)).getP());
}
/**
* Tests ElementListUtils.removeLegalBreaksFromEnd().
* @throws Exception if the test fails
*/
public void testRemoveElementFromEndPenalty2() throws Exception {
LinkedList lst = new LinkedList();
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, 0, false, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, 200, false, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthGlue(0, 0, 0, null, false));
lst.add(new KnuthBox(4000, null, false));
lst.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, null, false));
lst.add(new KnuthGlue(0, Integer.MAX_VALUE, 0, null, false));
lst.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, null, false));
boolean res = ElementListUtils.removeLegalBreaksFromEnd(lst, 9000);
assertFalse(res);

//Must insert an INFINITE penalty
assertEquals(0, ((KnuthPenalty)lst.get(1)).getP());
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getP());
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(5)).getP());
assertEquals(0, ((KnuthGlue)lst.get(6)).getW());
}
}

+ 123
- 0
test/layoutengine/standard-testcases/list-block_fox_orphan-content-limit_1.xml View File

<?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 the effect of the proprietary fox:orphan-content-limit property.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (4 * 1.2em)" space-before.conditionality="retain"/>
<fo:list-block
provisional-distance-between-starts="12pt" provisional-label-separation="5pt"
fox:orphan-content-limit="3 * 1.2em">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum, viverra ut, aliquam porttitor, convallis id, risus. Fusce malesuada nunc nec orci.</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum.</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
</fo:page-sequence>
<!-- the second page-sequence is without the extension property and just for reference. -->
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (4 * 1.2em)" space-before.conditionality="retain"/>
<fo:list-block
provisional-distance-between-starts="12pt" provisional-label-separation="5pt">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum, viverra ut, aliquam porttitor, convallis id, risus. Fusce malesuada nunc nec orci.</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum.</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<element-list category="breaker" index="0">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="302400" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
<element-list category="breaker" index="1">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="302400" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
</checks>
</testcase>

+ 123
- 0
test/layoutengine/standard-testcases/list-block_fox_widow-content-limit_1.xml View File

<?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 the effect of the proprietary fox:widow-content-limit property.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (2 * 1.2em)" space-before.conditionality="retain"/>
<fo:list-block
provisional-distance-between-starts="12pt" provisional-label-separation="5pt"
fox:widow-content-limit="3 * 1.2em">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum.</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum, viverra ut, aliquam porttitor, convallis id, risus. Fusce malesuada nunc nec orci.</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
</fo:page-sequence>
<!-- the second page-sequence is without the extension property and just for reference. -->
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (2 * 1.2em)" space-before.conditionality="retain"/>
<fo:list-block
provisional-distance-between-starts="12pt" provisional-label-separation="5pt">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum.</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum, viverra ut, aliquam porttitor, convallis id, risus. Fusce malesuada nunc nec orci.</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<element-list category="breaker" index="0">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="331200" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
<element-list category="breaker" index="1">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="331200" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
</checks>
</testcase>

+ 133
- 0
test/layoutengine/standard-testcases/table_fox_orphan-content-limit_1.xml View File

<?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 the effect of the proprietary fox:orphan-content-limit property.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (4 * 1.2em)" space-before.conditionality="retain"/>
<fo:table table-layout="fixed" width="100%" border-collapse="separate"
fox:orphan-content-limit="3 * 1.2em">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(3)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>row 1</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum, viverra ut, aliquam porttitor, convallis id, risus. Fusce malesuada nunc nec orci.</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>row 2</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
<!-- the second page-sequence is without the extension property and just for reference. -->
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (4 * 1.2em)" space-before.conditionality="retain"/>
<fo:table table-layout="fixed" width="100%" border-collapse="separate">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(3)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>row 1</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum, viverra ut, aliquam porttitor, convallis id, risus. Fusce malesuada nunc nec orci.</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>row 2</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<element-list category="breaker" index="0">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="302400" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
<element-list category="breaker" index="1">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="302400" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
</checks>
</testcase>

+ 133
- 0
test/layoutengine/standard-testcases/table_fox_widow-content-limit_1.xml View File

<?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 the effect of the proprietary fox:widow-content-limit property.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (2 * 1.2em)" space-before.conditionality="retain"/>
<fo:table table-layout="fixed" width="100%" border-collapse="separate"
fox:widow-content-limit="3 * 1.2em">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(3)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>row 1</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>row 2</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum, viverra ut, aliquam porttitor, convallis id, risus. Fusce malesuada nunc nec orci.</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
<!-- the second page-sequence is without the extension property and just for reference. -->
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (2 * 1.2em)" space-before.conditionality="retain"/>
<fo:table table-layout="fixed" width="100%" border-collapse="separate">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(3)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>row 1</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>row 2</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec felis ipsum, viverra ut, aliquam porttitor, convallis id, risus. Fusce malesuada nunc nec orci.</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<element-list category="breaker" index="0">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="331200" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
<element-list category="breaker" index="1">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="331200" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
</checks>
</testcase>

+ 97
- 0
test/layoutengine/standard-testcases/table_fox_widow-content-limit_2.xml View File

<?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 the effect of the proprietary fox:widow-content-limit property.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal" white-space-collapse="true" widows="0" orphans="0">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5in - (2 * 1.2em)" space-before.conditionality="retain"/>
<fo:table table-layout="fixed" width="100%" border-collapse="separate"
fox:widow-content-limit="3 * 1.2em">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(3)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>row 1</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet.</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>row 2</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet.</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>row 3</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet.</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>row 4</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Lorem ipsum dolor sit amet.</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<element-list category="breaker">
<box w="0"/>
<penalty w="0" p="INF"/>
<glue w="331200" y="0" z="0"/>
<box w="0"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>
<penalty w="0" p="INF"/>
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="14400"/>

<skip>3</skip>
</element-list>
</checks>
</testcase>

Loading…
Cancel
Save