You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2008/03/06 14:34:59 UTC
svn commit: r634267 [10/39] - in
/xmlgraphics/fop/branches/Temp_ProcessingFeedback: ./ examples/embedding/
examples/embedding/java/embedding/
examples/embedding/java/embedding/intermediate/ examples/embedding/xml/xml/
examples/fo/ examples/fo/advanced/...
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java Thu Mar 6 05:33:44 2008
@@ -27,8 +27,6 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fop.area.Block;
-import org.apache.fop.area.Trait;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
@@ -36,18 +34,17 @@
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
-import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthBox;
-import org.apache.fop.layoutmgr.KnuthPenalty;
+import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthPossPosIter;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition;
+import org.apache.fop.util.BreakUtil;
/**
* Layout manager for table contents, particularly managing the creation of combined element lists.
@@ -106,7 +103,7 @@
ColumnSetup getColumns() {
return getTableLM().getColumns();
}
-
+
/** @return the net header height */
protected int getHeaderNetHeight() {
return this.headerNetHeight;
@@ -207,52 +204,57 @@
private LinkedList getKnuthElementsForRowIterator(TableRowIterator iter,
LayoutContext context, int alignment, int bodyType) {
LinkedList returnList = new LinkedList();
- EffRow[] rowGroup = null;
- int breakBetween = Constants.EN_AUTO;
- while ((rowGroup = iter.getNextRowGroup()) != null) {
+ EffRow[] rowGroup = iter.getNextRowGroup();
+ // TODO homogenize the handling of keeps and breaks
+ context.unsetFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING
+ | LayoutContext.KEEP_WITH_NEXT_PENDING);
+ context.setBreakBefore(Constants.EN_AUTO);
+ context.setBreakAfter(Constants.EN_AUTO);
+ boolean keepWithPrevious = false;
+ int breakBefore = Constants.EN_AUTO;
+ if (rowGroup != null) {
RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup,
stepper);
- if (breakBetween == Constants.EN_AUTO) {
- // TODO improve
- breakBetween = rowGroupLM.getBreakBefore();
- }
- if (breakBetween != Constants.EN_AUTO) {
- if (returnList.size() > 0) {
- BreakElement breakPoss = (BreakElement) returnList.getLast();
- breakPoss.setPenaltyValue(-KnuthPenalty.INFINITE);
- breakPoss.setBreakClass(breakBetween);
- } else {
- returnList.add(new BreakElement(new Position(tableLM),
- 0, -KnuthPenalty.INFINITE, breakBetween, context));
+ List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType);
+ keepWithPrevious = context.isKeepWithPreviousPending();
+ boolean keepBetween = context.isKeepWithNextPending();
+ breakBefore = context.getBreakBefore();
+ int breakBetween = context.getBreakAfter();
+ returnList.addAll(nextRowGroupElems);
+ while ((rowGroup = iter.getNextRowGroup()) != null) {
+ rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, stepper);
+ nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType);
+ int penaltyValue = 0;
+ keepBetween |= context.isKeepWithPreviousPending();
+ if (keepBetween || tableLM.getTable().mustKeepTogether()) {
+ penaltyValue = KnuthElement.INFINITE;
}
- }
- returnList.addAll(rowGroupLM.getNextKnuthElements(context, alignment, bodyType));
- breakBetween = rowGroupLM.getBreakAfter();
- }
- // Break after the table's last row
- // TODO should eventually be handled at the table level
- if (breakBetween != Constants.EN_AUTO) {
- if (returnList.size() > 0 && ((ListElement) returnList.getLast()).isPenalty()) {
- // May be a glue if the unbroken height is greater than the broken heights
- BreakElement breakPoss = (BreakElement) returnList.getLast();
- breakPoss.setPenaltyValue(-KnuthPenalty.INFINITE);
- breakPoss.setBreakClass(breakBetween);
- } else {
- returnList.add(new BreakElement(new Position(tableLM),
- 0, -KnuthPenalty.INFINITE, breakBetween, context));
- }
- }
- if (returnList.size() > 0) {
- //Remove the last penalty produced by the combining algorithm (see TableStepper),
- //for the last step
- ListElement last = (ListElement)returnList.getLast();
- if (last.isPenalty() || last instanceof BreakElement) {
- if (!last.isForcedBreak()) {
- //Only remove if we don't signal a forced break
- returnList.removeLast();
+ breakBetween = BreakUtil.compareBreakClasses(breakBetween,
+ context.getBreakBefore());
+ if (breakBetween != Constants.EN_AUTO) {
+ penaltyValue = -KnuthElement.INFINITE;
+ }
+ TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM());
+ int penaltyLen = 0;
+ if (bodyType == TableRowIterator.BODY) {
+ if (!getTableLM().getTable().omitHeaderAtBreak()) {
+ penaltyLen += getHeaderNetHeight();
+ penaltyPos.headerElements = getHeaderElements();
+ }
+ if (!getTableLM().getTable().omitFooterAtBreak()) {
+ penaltyLen += getFooterNetHeight();
+ penaltyPos.footerElements = getFooterElements();
+ }
}
+ returnList.add(new BreakElement(penaltyPos,
+ penaltyLen, penaltyValue, breakBetween, context));
+ returnList.addAll(nextRowGroupElems);
+ breakBetween = context.getBreakAfter();
+ keepBetween = context.isKeepWithNextPending();
}
}
+ context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, keepWithPrevious);
+ context.setBreakBefore(breakBefore);
//fox:widow-content-limit
int widowContentLimit = getTableLM().getTable().getWidowContentLimit().getValue();
@@ -287,7 +289,7 @@
this.usedBPD = 0;
RowPainter painter = new RowPainter(this, layoutContext);
- List positions = new java.util.ArrayList();
+ List tablePositions = new ArrayList();
List headerElements = null;
List footerElements = null;
Position firstPos = null;
@@ -324,7 +326,7 @@
//ignore for now, see special handling below if break is at a penalty
//Only if the last position in this part/page us such a position it will be used
} else if (pos instanceof TableContentPosition) {
- positions.add(pos);
+ tablePositions.add(pos);
} else {
if (log.isDebugEnabled()) {
log.debug("Ignoring position: " + pos);
@@ -353,21 +355,23 @@
if (headerElements != null) {
//header positions for the last part are the second-to-last element and need to
//be handled first before all other TableContentPositions
- PositionIterator nestedIter = new KnuthPossPosIter(headerElements);
- iterateAndPaintPositions(nestedIter, painter, false);
+ addHeaderFooterAreas(headerElements, tableLM.getTable().getTableHeader(), painter,
+ false);
}
- //Iterate over all steps
- Iterator posIter = positions.iterator();
- painter.startBody();
- // Here we are sure that posIter iterates only over TableContentPosition instances
- iterateAndPaintPositions(posIter, painter, footerElements == null);
- painter.endBody();
+ if (tablePositions.isEmpty()) {
+ // TODO make sure this actually never happens
+ log.error("tablePositions empty."
+ + " Please send your FO file to fop-users@xmlgraphics.apache.org");
+ } else {
+ // Here we are sure that posIter iterates only over TableContentPosition instances
+ addBodyAreas(tablePositions.iterator(), painter, footerElements == null);
+ }
if (footerElements != null) {
//Positions for footers are simply added at the end
- PositionIterator nestedIter = new KnuthPossPosIter(footerElements);
- iterateAndPaintPositions(nestedIter, painter, true);
+ addHeaderFooterAreas(footerElements, tableLM.getTable().getTableFooter(), painter,
+ true);
}
this.usedBPD += painter.getAccumulatedBPD();
@@ -378,105 +382,73 @@
}
}
- /**
- * Iterates over a part of the table (header, footer, body) and paints the related
- * elements.
- *
- * @param iterator iterator over Position elements. Those positions correspond to the
- * elements of the table present on the current page
- * @param painter
- * @param lastOnPage true if the corresponding part will be the last on the page
- * (either body or footer, obviously)
- */
- private void iterateAndPaintPositions(Iterator iterator, RowPainter painter,
+ private void addHeaderFooterAreas(List elements, TableBody part, RowPainter painter,
boolean lastOnPage) {
- List lst = new ArrayList();
- boolean firstPos = false;
- TableBody body = null;
- while (iterator.hasNext()) {
- Position pos = (Position)iterator.next();
+ List lst = new ArrayList(elements.size());
+ for (Iterator iter = new KnuthPossPosIter(elements); iter.hasNext();) {
+ Position pos = (Position) iter.next();
+ /*
+ * Unlike for the body the Positions associated to the glues generated by
+ * TableStepper haven't been removed yet.
+ */
if (pos instanceof TableContentPosition) {
- TableContentPosition tcpos = (TableContentPosition)pos;
- lst.add(tcpos);
- CellPart part = (CellPart)tcpos.cellParts.get(0);
- if (body == null) {
- body = part.pgu.getBody();
- }
- if (tcpos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP)
- && tcpos.row.getFlag(EffRow.FIRST_IN_PART)) {
- firstPos = true;
-
- }
- if (tcpos.getFlag(TableContentPosition.LAST_IN_ROWGROUP)
- && tcpos.row.getFlag(EffRow.LAST_IN_PART)) {
- log.trace("LAST_IN_ROWGROUP + LAST_IN_PART");
- handleMarkersAndPositions(lst, body, firstPos, true, painter);
- //reset
- firstPos = false;
- body = null;
- lst.clear();
- }
+ lst.add((TableContentPosition) pos);
}
}
- if (body != null) {
- // Entering this block means that the end of the current table-part hasn't
- // been reached (otherwise it would have been caught by the test above). So
- // lastPos is necessarily false
- handleMarkersAndPositions(lst, body, firstPos, false, painter);
- }
- painter.addAreasAndFlushRow(true, lastOnPage);
- }
-
- private void handleMarkersAndPositions(List positions, TableBody body, boolean firstPos,
- boolean lastPos, RowPainter painter) {
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
- true, firstPos, lastPos);
- int size = positions.size();
- for (int i = 0; i < size; i++) {
- painter.handleTableContentPosition((TableContentPosition)positions.get(i));
- }
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
- false, firstPos, lastPos);
+ addTablePartAreas(lst, painter, part, true, true, true, lastOnPage);
}
/**
- * Get the area for a row for background.
- * @param row the table-row object or null
- * @return the row area or null if there's no background to paint
+ * Iterates over the positions corresponding to the table's body (which may contain
+ * several table-body elements!) and adds the corresponding areas.
+ *
+ * @param iterator iterator over TableContentPosition elements. Those positions
+ * correspond to the elements of the body present on the current page
+ * @param painter
+ * @param lastOnPage true if the table has no footer (then the last line of the table
+ * that will be present on the page belongs to the body)
*/
- Block getRowArea(TableRow row) {
- if (row == null || !row.getCommonBorderPaddingBackground().hasBackground()) {
- return null;
- } else {
- Block block = new Block();
- block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
- block.setPositioning(Block.ABSOLUTE);
- return block;
- }
+ private void addBodyAreas(Iterator iterator, RowPainter painter,
+ boolean lastOnPage) {
+ painter.startBody();
+ List lst = new ArrayList();
+ TableContentPosition pos = (TableContentPosition) iterator.next();
+ boolean isFirstPos = pos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP)
+ && pos.getRow().getFlag(EffRow.FIRST_IN_PART);
+ TableBody body = pos.getTableBody();
+ lst.add(pos);
+ while (iterator.hasNext()) {
+ pos = (TableContentPosition) iterator.next();
+ if (pos.getTableBody() != body) {
+ addTablePartAreas(lst, painter, body, isFirstPos, true, false, false);
+ isFirstPos = true;
+ lst.clear();
+ body = pos.getTableBody();
+ }
+ lst.add(pos);
+ }
+ boolean isLastPos = pos.getFlag(TableContentPosition.LAST_IN_ROWGROUP)
+ && pos.getRow().getFlag(EffRow.LAST_IN_PART);
+ addTablePartAreas(lst, painter, body, isFirstPos, isLastPos, true, lastOnPage);
+ painter.endBody();
}
/**
- * Adds the area for the row background if any.
- * @param row row for which to generate the background
- * @param bpd block-progression-dimension of the row
- * @param ipd inline-progression-dimension of the row
- * @param yoffset Y offset at which to paint
+ * Adds the areas corresponding to a single fo:table-header/footer/body element.
*/
- void addRowBackgroundArea(TableRow row, int bpd, int ipd, int yoffset) {
- //Add row background if any
- Block rowBackground = getRowArea(row);
- if (rowBackground != null) {
- rowBackground.setBPD(bpd);
- rowBackground.setIPD(ipd);
- rowBackground.setXOffset(this.startXOffset);
- rowBackground.setYOffset(yoffset);
- getTableLM().addChildArea(rowBackground);
- TraitSetter.addBackground(rowBackground,
- row.getCommonBorderPaddingBackground(), getTableLM());
+ private void addTablePartAreas(List positions, RowPainter painter, TableBody body,
+ boolean isFirstPos, boolean isLastPos, boolean lastInBody, boolean lastOnPage) {
+ getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
+ true, isFirstPos, isLastPos);
+ painter.startTablePart(body);
+ for (Iterator iter = positions.iterator(); iter.hasNext();) {
+ painter.handleTableContentPosition((TableContentPosition) iter.next());
}
+ getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
+ false, isFirstPos, isLastPos);
+ painter.endTablePart(lastInBody, lastOnPage);
}
-
-
+
/**
* Sets the overall starting x-offset. Used for proper placement of cells.
* @param startXOffset starting x-offset (table's start-indent)
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Mar 6 05:33:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java Thu Mar 6 05:33:44 2008
@@ -22,6 +22,7 @@
import java.util.List;
import org.apache.fop.fo.flow.table.EffRow;
+import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.Position;
@@ -39,10 +40,12 @@
/** the list of CellParts making up this position */
protected List cellParts;
/** effective row this position belongs to */
- protected EffRow row;
+ private EffRow row;
/** flags for the position */
protected int flags;
+ private EffRow newPageRow;
+
/**
* Creates a new TableContentPosition.
* @param lm applicable layout manager
@@ -54,6 +57,31 @@
super(lm);
this.cellParts = cellParts;
this.row = row;
+ this.newPageRow = row;
+ }
+
+ /**
+ * Sets the row corresponding to this position if it starts a new page. In which case,
+ * if the delay mechanism is on, this is the delayed row that starts the page, and not
+ * the current row being extended.
+ *
+ * @param newPageRow the row that will start the page if this position is the first
+ * one on that page
+ */
+ void setNewPageRow(EffRow newPageRow) {
+ this.newPageRow = newPageRow;
+ }
+
+ EffRow getNewPageRow() {
+ return newPageRow;
+ }
+
+ EffRow getRow() {
+ return row;
+ }
+
+ TableBody getTableBody() {
+ return ((CellPart) cellParts.get(0)).pgu.getTableBody();
}
/**
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java Thu Mar 6 05:33:44 2008
@@ -19,31 +19,34 @@
package org.apache.fop.layoutmgr.table;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.datatypes.LengthBase;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.ListElement;
-import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.RelSide;
import org.apache.fop.layoutmgr.TraitSetter;
-import org.apache.fop.area.Area;
-import org.apache.fop.area.Block;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import org.apache.fop.datatypes.LengthBase;
-import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.FObj;
+import org.apache.fop.util.BreakUtil;
/**
* LayoutManager for a table FO.
@@ -78,7 +81,27 @@
private int halfBorderSeparationBPD;
private int halfBorderSeparationIPD;
-
+
+ /** See {@link TableLayoutManager#registerColumnBackgroundArea(TableColumn, Block, int)}. */
+ private List columnBackgroundAreas;
+
+ /**
+ * Temporary holder of column background informations for a table-cell's area.
+ *
+ * @see TableLayoutManager#registerColumnBackgroundArea(TableColumn, Block, int)
+ */
+ private static final class ColumnBackgroundInfo {
+ private TableColumn column;
+ private Block backgroundArea;
+ private int xShift;
+
+ private ColumnBackgroundInfo(TableColumn column, Block backgroundArea, int xShift) {
+ this.column = column;
+ this.backgroundArea = backgroundArea;
+ this.xShift = xShift;
+ }
+ }
+
/**
* Create a new table layout manager.
* @param node the table FO
@@ -150,25 +173,11 @@
public int getHalfBorderSeparationIPD() {
return halfBorderSeparationIPD;
}
-
- /**
- * Handles the Knuth elements at the table level: mainly breaks, spaces and borders
- * before and after the table. The Knuth elements for the table cells are handled by
- * TableContentLayoutManager.
- *
- * @see org.apache.fop.layoutmgr.LayoutManager
- * @see TableContentLayoutManager#getNextKnuthElements(LayoutContext, int)
- */
+
+ /** {@inheritDoc} */
public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
LinkedList returnList = new LinkedList();
-
- if (!breakBeforeServed) {
- breakBeforeServed = true;
- if (addKnuthElementsForBreakBefore(returnList, context)) {
- return returnList;
- }
- }
/*
* Compute the IPD and adjust it if necessary (overconstrained)
@@ -225,10 +234,7 @@
// Elements for the table-header/footer/body
LinkedList contentKnuthElements = null;
- LinkedList contentList = new LinkedList();
- //Position returnPosition = new NonLeafPosition(this, null);
- //Body prevLM = null;
-
+ contentLM = new TableContentLayoutManager(this);
LayoutContext childLC = new LayoutContext(0);
/*
childLC.setStackLimit(
@@ -237,46 +243,7 @@
childLC.setRefIPD(context.getRefIPD());
childLC.copyPendingMarksFrom(context);
- if (contentLM == null) {
- contentLM = new TableContentLayoutManager(this);
- }
contentKnuthElements = contentLM.getNextKnuthElements(childLC, alignment);
- if (childLC.isKeepWithNextPending()) {
- log.debug("TableContentLM signals pending keep-with-next");
- context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
- }
- if (childLC.isKeepWithPreviousPending()) {
- log.debug("TableContentLM signals pending keep-with-previous");
- context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
- }
-
- // Check if the table's content starts/ends with a forced break
- // TODO this is hacky and will need to be handled better eventually
- if (contentKnuthElements.size() > 0) {
- ListElement element = (ListElement)contentKnuthElements.getFirst();
- if (element.isForcedBreak()) {
- // The first row of the table(-body), or (the content of) one of its cells
- // has a forced break-before
- int breakBeforeTable = ((Table) fobj).getBreakBefore();
- if (breakBeforeTable == EN_PAGE
- || breakBeforeTable == EN_COLUMN
- || breakBeforeTable == EN_EVEN_PAGE
- || breakBeforeTable == EN_ODD_PAGE) {
- // There is already a forced break before the table; remove this one
- // to prevent a double break
- contentKnuthElements.removeFirst();
- } else {
- element.setPosition(new NonLeafPosition(this, null));
- }
- }
- element = (ListElement)contentKnuthElements.getLast();
- if (element.isForcedBreak()) {
- // The last row of the table(-body), or (the content of) one of its cells
- // has a forced break-after
- element.setPosition(new NonLeafPosition(this, null));
- }
- }
-
//Set index values on elements coming from the content LM
Iterator iter = contentKnuthElements.iterator();
while (iter.hasNext()) {
@@ -284,24 +251,64 @@
notifyPos(el.getPosition());
}
log.debug(contentKnuthElements);
- contentList.addAll(contentKnuthElements);
- wrapPositionElements(contentList, returnList);
+ wrapPositionElements(contentKnuthElements, returnList);
+
+ if (mustKeepWithPrevious() || childLC.isKeepWithPreviousPending()) {
+ context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+ }
+ if (mustKeepWithNext() || childLC.isKeepWithNextPending()) {
+ context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+ }
+
if (getTable().isSeparateBorderModel()) {
addKnuthElementsForBorderPaddingAfter(returnList, true);
}
addKnuthElementsForSpaceAfter(returnList, alignment);
- addKnuthElementsForBreakAfter(returnList, context);
- if (mustKeepWithNext()) {
- context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+
+ //addKnuthElementsForBreakBefore(returnList, context);
+ int breakBefore = BreakUtil.compareBreakClasses(getTable().getBreakBefore(),
+ childLC.getBreakBefore());
+ if (breakBefore != Constants.EN_AUTO) {
+ returnList.addFirst(new BreakElement(getAuxiliaryPosition(),
+ 0, -KnuthElement.INFINITE, breakBefore, context));
}
- if (mustKeepWithPrevious()) {
- context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+
+ //addKnuthElementsForBreakAfter(returnList, context);
+ int breakAfter = BreakUtil.compareBreakClasses(getTable().getBreakAfter(),
+ childLC.getBreakAfter());
+ if (breakAfter != Constants.EN_AUTO) {
+ returnList.add(new BreakElement(getAuxiliaryPosition(),
+ 0, -KnuthElement.INFINITE, breakAfter, context));
}
+
setFinished(true);
resetSpaces();
return returnList;
}
-
+
+ /**
+ * Registers the given area, that will be used to render the part of column background
+ * covered by a table-cell. If percentages are used to place the background image, the
+ * final bpd of the (fraction of) table that will be rendered on the current page must
+ * be known. The traits can't then be set when the areas for the cell are created
+ * since at that moment this bpd is yet unknown. So they will instead be set in
+ * TableLM's {@link #addAreas(PositionIterator, LayoutContext)} method.
+ *
+ * @param column the table-column element from which the cell gets background
+ * informations
+ * @param backgroundArea the block of the cell's dimensions that will hold the column
+ * background
+ * @param xShift additional amount by which the image must be shifted to be correctly
+ * placed (to counterbalance the cell's start border)
+ */
+ void registerColumnBackgroundArea(TableColumn column, Block backgroundArea, int xShift) {
+ addBackgroundArea(backgroundArea);
+ if (columnBackgroundAreas == null) {
+ columnBackgroundAreas = new ArrayList();
+ }
+ columnBackgroundAreas.add(new ColumnBackgroundInfo(column, backgroundArea, xShift));
+ }
+
/**
* The table area is a reference area that contains areas for
* columns, bodies, rows and the contents are in cells.
@@ -336,6 +343,17 @@
curBlockArea.setBPD(tableHeight);
+ if (columnBackgroundAreas != null) {
+ for (Iterator iter = columnBackgroundAreas.iterator(); iter.hasNext();) {
+ ColumnBackgroundInfo b = (ColumnBackgroundInfo) iter.next();
+ TraitSetter.addBackground(b.backgroundArea,
+ b.column.getCommonBorderPaddingBackground(), this,
+ b.xShift, -b.backgroundArea.getYOffset(),
+ b.column.getColumnWidth().getValue(this), tableHeight);
+ }
+ columnBackgroundAreas.clear();
+ }
+
if (getTable().isSeparateBorderModel()) {
TraitSetter.addBorders(curBlockArea,
getTable().getCommonBorderPaddingBackground(),
@@ -402,6 +420,15 @@
if (curBlockArea != null) {
curBlockArea.addBlock((Block) childArea);
}
+ }
+
+ /**
+ * Adds the given area to this layout manager's area, without updating the used bpd.
+ *
+ * @param background an area
+ */
+ void addBackgroundArea(Block background) {
+ curBlockArea.addChildArea(background);
}
/** {@inheritDoc} */
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Mar 6 05:33:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Mar 6 05:33:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableStepper.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableStepper.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableStepper.java Thu Mar 6 05:33:44 2008
@@ -26,17 +26,16 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.Constants;
-import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
-import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.KnuthPenalty;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.util.BreakUtil;
/**
* This class processes row groups to create combined element lists for tables.
@@ -52,51 +51,69 @@
/** Number of columns in the row group. */
private int columnCount;
private int totalHeight;
- private int previousRowsLength = 0;
+ private int previousRowsLength;
private int activeRowIndex;
- private boolean rowBacktrackForLastStep;
- private boolean skippedStep;
+ private boolean rowFinished;
+
+ /** Cells spanning the current row. */
private List activeCells = new LinkedList();
+ /** Cells that will start the next row. */
+ private List nextActiveCells = new LinkedList();
+
/**
- * Main constructor
- * @param tclm The parent TableContentLayoutManager
+ * True if the next row is being delayed, that is, if cells spanning the current and
+ * the next row have steps smaller than the next row's first step. In this case the
+ * next row may be extended to offer additional break possibilities.
*/
- public TableStepper(TableContentLayoutManager tclm) {
- this.tclm = tclm;
- this.columnCount = tclm.getTableLM().getTable().getNumberOfColumns();
- }
+ private boolean delayingNextRow;
/**
- * Initializes the fields of this instance to handle a new row group.
+ * The first step for a row. This is the minimal step necessary to include some
+ * content from all the cells starting the row.
+ */
+ private int rowFirstStep;
+
+ /**
+ * Flag used to produce an infinite penalty if the height of the current row is
+ * smaller than the first step for that row (may happen with row-spanning cells).
*
- * @param rowGroup the new row group to handle
+ * @see #considerRowLastStep(int)
*/
- private void setup(EffRow[] rowGroup) {
- this.rowGroup = rowGroup;
- this.activeRowIndex = 0;
- this.previousRowsLength = 0;
- }
+ private boolean rowHeightSmallerThanFirstStep;
/**
- * Returns the row currently being processed.
- *
- * @return the row currently being processed
+ * The class of the next break. One of {@link Constants#EN_AUTO},
+ * {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE},
+ * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}. Defaults to
+ * EN_AUTO.
*/
- private EffRow getActiveRow() {
- return rowGroup[activeRowIndex];
+ private int nextBreakClass;
+
+ /**
+ * Main constructor
+ * @param tclm The parent TableContentLayoutManager
+ */
+ public TableStepper(TableContentLayoutManager tclm) {
+ this.tclm = tclm;
+ this.columnCount = tclm.getTableLM().getTable().getNumberOfColumns();
}
/**
- * Returns the grid unit at the given column number on the active row.
- *
- * @param column column number of the grid unit to get
- * @return the corresponding grid unit (may be null)
- * {@inheritDoc}
+ * Initializes the fields of this instance to handle a new row group.
+ *
+ * @param rows the new row group to handle
*/
- private GridUnit getActiveGridUnit(int column) {
- return getActiveRow().safelyGetGridUnit(column);
+ private void setup(EffRow[] rows) {
+ rowGroup = rows;
+ previousRowsLength = 0;
+ activeRowIndex = 0;
+ activeCells.clear();
+ nextActiveCells.clear();
+ delayingNextRow = false;
+ rowFirstStep = 0;
+ rowHeightSmallerThanFirstStep = false;
}
private void calcTotalHeight() {
@@ -111,30 +128,34 @@
private int getMaxRemainingHeight() {
int maxW = 0;
- if (!rowBacktrackForLastStep) {
- for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
- maxW = Math.max(maxW,
- ((ActiveCell) iter.next()).getRemainingHeight(activeRowIndex));
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ int remain = activeCell.getRemainingLength();
+ PrimaryGridUnit pgu = activeCell.getPrimaryGridUnit();
+ for (int i = activeRowIndex + 1; i < pgu.getRowIndex() - rowGroup[0].getIndex()
+ + pgu.getCell().getNumberRowsSpanned(); i++) {
+ remain -= rowGroup[i].getHeight().opt;
}
+ maxW = Math.max(maxW, remain);
}
- for (int i = activeRowIndex + (rowBacktrackForLastStep ? 0 : 1); i < rowGroup.length; i++) {
+ for (int i = activeRowIndex + 1; i < rowGroup.length; i++) {
maxW += rowGroup[i].getHeight().opt;
}
- log.debug("maxRemainingHeight=" + maxW);
return maxW;
}
/**
- * Initializes the informations relative to the Knuth elements, to handle a new row in
- * the current row group.
+ * Creates ActiveCell instances for cells starting on the row at the given index.
+ *
+ * @param activeCellList the list that will hold the active cells
+ * @param rowIndex the index of the row from which cells must be activated
*/
- private void initializeElementLists() {
- log.trace("Entering initializeElementLists()");
- EffRow row = getActiveRow();
+ private void activateCells(List activeCellList, int rowIndex) {
+ EffRow row = rowGroup[rowIndex];
for (int i = 0; i < columnCount; i++) {
- GridUnit gu = getActiveGridUnit(i);
- if (gu != null && !gu.isEmpty() && gu.isPrimary()) {
- activeCells.add(new ActiveCell((PrimaryGridUnit) gu, row, activeRowIndex,
+ GridUnit gu = row.getGridUnit(i);
+ if (!gu.isEmpty() && gu.isPrimary()) {
+ activeCellList.add(new ActiveCell((PrimaryGridUnit) gu, row, rowIndex,
previousRowsLength, getTableLM()));
}
}
@@ -143,61 +164,55 @@
/**
* Creates the combined element list for a row group.
* @param context Active LayoutContext
- * @param rowGroup the row group
+ * @param rows the row group
* @param bodyType Indicates what type of body is processed (body, header or footer)
* @return the combined element list
*/
- public LinkedList getCombinedKnuthElementsForRowGroup(LayoutContext context, EffRow[] rowGroup,
+ public LinkedList getCombinedKnuthElementsForRowGroup(LayoutContext context, EffRow[] rows,
int bodyType) {
- setup(rowGroup);
- initializeElementLists();
+ setup(rows);
+ activateCells(activeCells, 0);
calcTotalHeight();
- boolean signalKeepWithNext = false;
- int laststep = 0;
- int step;
int cumulateLength = 0; // Length of the content accumulated before the break
TableContentPosition lastTCPos = null;
LinkedList returnList = new LinkedList();
- while ((step = getNextStep()) >= 0) {
- int normalRow = activeRowIndex;
- int increase = step - laststep;
- int penaltyOrGlueLen = step + getMaxRemainingHeight() - totalHeight;
- int boxLen = step - cumulateLength - Math.max(0, penaltyOrGlueLen)/* the penalty, if any */;
+ int laststep = 0;
+ int step = getFirstStep();
+ do {
+ int maxRemainingHeight = getMaxRemainingHeight();
+ int penaltyOrGlueLen = step + maxRemainingHeight - totalHeight;
+ int boxLen = step - cumulateLength - Math.max(0, penaltyOrGlueLen)/* penalty, if any */;
cumulateLength += boxLen + Math.max(0, -penaltyOrGlueLen)/* the glue, if any */;
- boolean forcedBreak = false;
- int breakClass = -1;
+ if (log.isDebugEnabled()) {
+ log.debug("Next step: " + step + " (+" + (step - laststep) + ")");
+ log.debug(" max remaining height: " + maxRemainingHeight);
+ if (penaltyOrGlueLen >= 0) {
+ log.debug(" box = " + boxLen + " penalty = " + penaltyOrGlueLen);
+ } else {
+ log.debug(" box = " + boxLen + " glue = " + (-penaltyOrGlueLen));
+ }
+ }
+
//Put all involved grid units into a list
List cellParts = new java.util.ArrayList(columnCount);
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
CellPart part = activeCell.createCellPart();
cellParts.add(part);
- if (activeCell.contributesContent()) {
- forcedBreak = activeCell.isLastForcedBreak();
- if (forcedBreak) {
- breakClass = activeCell.getLastBreakClass();
- }
- }
- if (returnList.size() == 0 && part.isFirstPart()
- && part.mustKeepWithPrevious()) {
- context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
- }
}
- //log.debug(">>> guPARTS: " + cellParts);
//Create elements for step
TableContentPosition tcpos = new TableContentPosition(getTableLM(),
- cellParts, rowGroup[normalRow]);
+ cellParts, rowGroup[activeRowIndex]);
+ if (delayingNextRow) {
+ tcpos.setNewPageRow(rowGroup[activeRowIndex + 1]);
+ }
if (returnList.size() == 0) {
tcpos.setFlag(TableContentPosition.FIRST_IN_ROWGROUP, true);
}
lastTCPos = tcpos;
- if (log.isDebugEnabled()) {
- log.debug(" - backtrack=" + rowBacktrackForLastStep
- + " - row=" + activeRowIndex + " - " + tcpos);
- }
returnList.add(new KnuthBox(boxLen, tcpos, false));
int effPenaltyLen = Math.max(0, penaltyOrGlueLen);
@@ -214,77 +229,126 @@
}
int p = 0;
- boolean allCellsHaveContributed = true;
- signalKeepWithNext = false;
+ boolean keepWithNext = false;
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- allCellsHaveContributed &= activeCell.hasStarted();
- signalKeepWithNext |= activeCell.keepWithNextSignal();
+ keepWithNext |= activeCell.keepWithNextSignal();
}
- if (!allCellsHaveContributed) {
- //Not all cells have contributed to a newly started row. The penalty here is
- //used to avoid breaks resulting in badly broken tables.
- //See also: http://marc.theaimsgroup.com/?t=112248999600005&r=1&w=2
- p = 900; //KnuthPenalty.INFINITE; //TODO Arbitrary value. Please refine.
- }
- if (signalKeepWithNext || getTableLM().mustKeepTogether()) {
- p = KnuthPenalty.INFINITE;
- }
- if (skippedStep) {
+ if (keepWithNext || getTableLM().mustKeepTogether()) {
p = KnuthPenalty.INFINITE;
- //Need to avoid breaking because borders and/or paddding from other columns would
- //not fit in the available space (see getNextStep())
}
- if (forcedBreak) {
- if (skippedStep) {
- log.error("This is a conflict situation. The output may be wrong."
- + " Please send your FO file to fop-dev@xmlgraphics.apache.org!");
+ if (!rowFinished) {
+ if (rowGroup[activeRowIndex].mustKeepTogether()) {
+ p = KnuthPenalty.INFINITE;
+ }
+ } else if (activeRowIndex < rowGroup.length - 1) {
+ if (rowGroup[activeRowIndex].mustKeepWithNext()
+ || rowGroup[activeRowIndex + 1].mustKeepWithPrevious()) {
+ p = KnuthPenalty.INFINITE;
}
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ rowGroup[activeRowIndex].getBreakAfter());
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ rowGroup[activeRowIndex + 1].getBreakBefore());
+ }
+ if (nextBreakClass != Constants.EN_AUTO) {
+ log.trace("Forced break encountered");
p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
}
- returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context));
+ if (rowHeightSmallerThanFirstStep) {
+ rowHeightSmallerThanFirstStep = false;
+ p = KnuthPenalty.INFINITE;
+ }
+ returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, nextBreakClass, context));
if (penaltyOrGlueLen < 0) {
returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true));
}
- if (log.isDebugEnabled()) {
- log.debug("step=" + step + " (+" + increase + ")"
- + " box=" + boxLen
- + " penalty=" + penaltyOrGlueLen
- + " effPenalty=" + effPenaltyLen);
- }
-
laststep = step;
- }
- if (signalKeepWithNext) {
- //Last step signalled a keep-with-next. Since the last penalty will be removed,
- //we have to signal the still pending last keep-with-next using the LayoutContext.
- context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
- }
- if (lastTCPos != null) {
+ step = getNextStep();
+ } while (step >= 0);
+ if (!returnList.isEmpty()) {
lastTCPos.setFlag(TableContentPosition.LAST_IN_ROWGROUP, true);
+ // It's not up to TableStepper to decide whether there can/must be a break
+ // after the row group or not, but to ancestor stacking elements
+ assert returnList.getLast() instanceof BreakElement;
+ returnList.removeLast();
}
return returnList;
}
/**
- * Finds the smallest increment leading to the next legal break inside the row-group.
+ * Returns the first step for the current row group.
*
- * @return the size of the increment, -1 if no next step is available (end of row-group reached)
+ * @return the first step for the current row group
+ */
+ private int getFirstStep() {
+ computeRowFirstStep(activeCells);
+ signalRowFirstStep();
+ int minStep = considerRowLastStep(rowFirstStep);
+ signalNextStep(minStep);
+ return minStep;
+ }
+
+ /**
+ * Returns the next break possibility.
+ *
+ * @return the next step
*/
private int getNextStep() {
- log.trace("Entering getNextStep");
- //Check for forced break conditions
- /*
- if (isBreakCondition()) {
- return -1;
- }*/
+ if (rowFinished) {
+ if (activeRowIndex == rowGroup.length - 1) {
+ // The row group is finished, no next step
+ return -1;
+ }
+ rowFinished = false;
+ removeCellsEndingOnCurrentRow();
+ log.trace("Delaying next row");
+ delayingNextRow = true;
+ }
+ if (delayingNextRow) {
+ int minStep = computeMinStep();
+ if (minStep < 0 || minStep >= rowFirstStep
+ || minStep > rowGroup[activeRowIndex].getExplicitHeight().max) {
+ if (log.isTraceEnabled()) {
+ log.trace("Step = " + minStep);
+ }
+ delayingNextRow = false;
+ minStep = rowFirstStep;
+ switchToNextRow();
+ signalRowFirstStep();
+ minStep = considerRowLastStep(minStep);
+ }
+ signalNextStep(minStep);
+ return minStep;
+ } else {
+ int minStep = computeMinStep();
+ minStep = considerRowLastStep(minStep);
+ signalNextStep(minStep);
+ return minStep;
+ }
+ }
- //set starting points
- goToNextRowIfCurrentFinished();
+ /**
+ * Computes the minimal necessary step to make the next row fit. That is, so such as
+ * cell on the next row can contribute some content.
+ *
+ * @param cells the cells occupying the next row (may include cells starting on
+ * previous rows and spanning over this one)
+ */
+ private void computeRowFirstStep(List cells) {
+ for (Iterator iter = cells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ rowFirstStep = Math.max(rowFirstStep, activeCell.getFirstStep());
+ }
+ }
- //Get next possible sequence for each cell
- //Determine smallest possible step
+ /**
+ * Computes the next minimal step.
+ *
+ * @return the minimal step from the active cells, < 0 if there is no such step
+ */
+ private int computeMinStep() {
int minStep = Integer.MAX_VALUE;
boolean stepFound = false;
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
@@ -295,78 +359,139 @@
minStep = Math.min(minStep, nextStep);
}
}
- if (!stepFound) {
+ if (stepFound) {
+ return minStep;
+ } else {
return -1;
}
+ }
+ /**
+ * Signals the first step to the active cells, to allow them to add more content to
+ * the step if possible.
+ *
+ * @see ActiveCell#signalRowFirstStep(int)
+ */
+ private void signalRowFirstStep() {
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ activeCell.signalRowFirstStep(rowFirstStep);
+ }
+ }
- //Reset bigger-than-minimum sequences
- //See http://people.apache.org/~jeremias/fop/NextStepAlgoNotes.pdf
- rowBacktrackForLastStep = false;
- skippedStep = false;
+ /**
+ * Signals the next selected step to the active cells.
+ *
+ * @param step the next step
+ */
+ private void signalNextStep(int step) {
+ nextBreakClass = Constants.EN_AUTO;
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- if (activeCell.signalMinStep(minStep)) {
- if (activeRowIndex == 0) {
- log.debug(" First row. Skip this step.");
- skippedStep = true;
- } else {
- log.debug(" row-span situation: backtracking to last row");
- //Stay on the previous row for another step because borders and padding on
- //columns may make their contribution to the step bigger than the addition
- //of the next element for this step would make the step to grow.
- rowBacktrackForLastStep = true;
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ activeCell.signalNextStep(step));
+ }
+ }
+
+ /**
+ * Determines if the given step will finish the current row, and if so switch to the
+ * last step for this row.
+ * <p>If the row is finished then the after borders for the cell may change (their
+ * conditionalities no longer apply for the cells ending on the current row). Thus the
+ * final step may grow with respect to the given one.</p>
+ * <p>In more rare occasions, the given step may correspond to the first step of a
+ * row-spanning cell, and may be greater than the height of the current row (consider,
+ * for example, an unbreakable cell spanning three rows). In such a case the returned
+ * step will correspond to the row height and a flag will be set to produce an
+ * infinite penalty for this step. This will prevent the breaking algorithm from
+ * choosing this break, but still allow to create the appropriate TableContentPosition
+ * for the cells ending on the current row.</p>
+ *
+ * @param step the next step
+ * @return the updated step if any
+ */
+ private int considerRowLastStep(int step) {
+ rowFinished = true;
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ if (activeCell.endsOnRow(activeRowIndex)) {
+ rowFinished &= activeCell.finishes(step);
+ }
+ }
+ if (rowFinished) {
+ if (log.isTraceEnabled()) {
+ log.trace("Step = " + step);
+ log.trace("Row finished, computing last step");
+ }
+ int maxStep = 0;
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ if (activeCell.endsOnRow(activeRowIndex)) {
+ maxStep = Math.max(maxStep, activeCell.getLastStep());
}
}
+ if (log.isTraceEnabled()) {
+ log.trace("Max step: " + maxStep);
+ }
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ activeCell.endRow(activeRowIndex);
+ if (!activeCell.endsOnRow(activeRowIndex)) {
+ activeCell.signalRowLastStep(maxStep);
+ }
+ }
+ if (maxStep < step) {
+ log.trace("Row height smaller than first step, produced penalty will be infinite");
+ rowHeightSmallerThanFirstStep = true;
+ }
+ step = maxStep;
+ prepareNextRow();
}
+ return step;
+ }
- return minStep;
+ /**
+ * Pre-activates the cells that will start the next row, and computes the first step
+ * for that row.
+ */
+ private void prepareNextRow() {
+ if (activeRowIndex < rowGroup.length - 1) {
+ previousRowsLength += rowGroup[activeRowIndex].getHeight().opt;
+ activateCells(nextActiveCells, activeRowIndex + 1);
+ if (log.isTraceEnabled()) {
+ log.trace("Computing first step for row " + (activeRowIndex + 2));
+ }
+ computeRowFirstStep(nextActiveCells);
+ if (log.isTraceEnabled()) {
+ log.trace("Next first step = " + rowFirstStep);
+ }
+ }
}
private void removeCellsEndingOnCurrentRow() {
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- activeCell.endRow(activeRowIndex);
if (activeCell.endsOnRow(activeRowIndex)) {
iter.remove();
}
}
}
- private void goToNextRowIfCurrentFinished() {
- // We assume that the current grid row is finished. If this is not the case this
- // boolean will be reset
- boolean currentGridRowFinished = true;
+ /**
+ * Actually switches to the next row, increasing activeRowIndex and transferring to
+ * activeCells the cells starting on the next row.
+ */
+ private void switchToNextRow() {
+ activeRowIndex++;
+ if (log.isTraceEnabled()) {
+ log.trace("Switching to row " + (activeRowIndex + 1));
+ }
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- if (activeCell.endsOnRow(activeRowIndex)) {
- currentGridRowFinished &= activeCell.isFinished();
- }
- }
-
- if (currentGridRowFinished) {
- removeCellsEndingOnCurrentRow();
- if (activeRowIndex < rowGroup.length - 1) {
- TableRow rowFO = getActiveRow().getTableRow();
- if (rowFO != null && rowFO.getBreakAfter() != Constants.EN_AUTO) {
- log.warn(FONode.decorateWithContextInfo(
- "break-after ignored on table-row because of row spanning "
- + "in progress (See XSL 1.0, 7.19.1)", rowFO));
- }
- previousRowsLength += rowGroup[activeRowIndex].getHeight().opt;
- activeRowIndex++;
- if (log.isDebugEnabled()) {
- log.debug("===> new row: " + activeRowIndex);
- }
- initializeElementLists();
- rowFO = getActiveRow().getTableRow();
- if (rowFO != null && rowFO.getBreakBefore() != Constants.EN_AUTO) {
- log.warn(FONode.decorateWithContextInfo(
- "break-before ignored on table-row because of row spanning "
- + "in progress (See XSL 1.0, 7.19.2)", rowFO));
- }
- }
+ activeCell.nextRowStarts();
}
+ activeCells.addAll(nextActiveCells);
+ nextActiveCells.clear();
}
/** @return the table layout manager */
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Mar 6 05:33:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/AlphaRasterImage.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/AlphaRasterImage.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/AlphaRasterImage.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/AlphaRasterImage.java Thu Mar 6 05:33:44 2008
@@ -22,6 +22,8 @@
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
import java.io.IOException;
import java.io.OutputStream;
@@ -137,18 +139,37 @@
throw new UnsupportedOperationException(
"Expected only one band/component for the alpha channel");
}
+
+ //...and write the Raster line by line with a reusable buffer
int dataType = alpha.getDataBuffer().getDataType();
- if (dataType != DataBuffer.TYPE_BYTE) {
+ if (dataType == DataBuffer.TYPE_BYTE) {
+ byte[] line = new byte[nbands * w];
+ for (int y = 0; y < h; y++) {
+ alpha.getDataElements(0, y, w, 1, line);
+ out.write(line);
+ }
+ } else if (dataType == DataBuffer.TYPE_INT) {
+ //Is there an better way to get a 8bit raster from a TYPE_INT raster?
+ int shift = 24;
+ SampleModel sampleModel = alpha.getSampleModel();
+ if (sampleModel instanceof SinglePixelPackedSampleModel) {
+ SinglePixelPackedSampleModel m = (SinglePixelPackedSampleModel)sampleModel;
+ shift = m.getBitOffsets()[0];
+ }
+ int[] iline = new int[nbands * w];
+ byte[] line = new byte[nbands * w];
+ for (int y = 0; y < h; y++) {
+ alpha.getDataElements(0, y, w, 1, iline);
+ for (int i = 0; i < w; i++) {
+ line[i] = (byte)(iline[i] >> shift);
+ }
+ out.write(line);
+ }
+ } else {
throw new UnsupportedOperationException("Unsupported DataBuffer type: "
+ alpha.getDataBuffer().getClass().getName());
}
- //...and write the Raster line by line with a reusable buffer
- byte[] line = new byte[nbands * w];
- for (int y = 0; y < h; y++) {
- alpha.getDataElements(0, y, w, 1, line);
- out.write(line);
- }
}
/** {@inheritDoc} */
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFAMode.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFArray.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFArray.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFArray.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFArray.java Thu Mar 6 05:33:44 2008
@@ -69,6 +69,20 @@
/**
* Create an array object.
* @param parent the array's parent if any
+ * @param values the actual array wrapped by this object
+ */
+ public PDFArray(PDFObject parent, double[] values) {
+ /* generic creation of PDF object */
+ super(parent);
+
+ for (int i = 0, c = values.length; i < c; i++) {
+ this.values.add(new Double(values[i]));
+ }
+ }
+
+ /**
+ * Create an array object.
+ * @param parent the array's parent if any
* @param values the actual values wrapped by this object
*/
public PDFArray(PDFObject parent, Collection values) {
@@ -133,7 +147,10 @@
*/
public void add(Object obj) {
if (obj instanceof PDFObject) {
- ((PDFObject)obj).setParent(this);
+ PDFObject pdfObj = (PDFObject)obj;
+ if (!pdfObj.hasObjectNumber()) {
+ pdfObj.setParent(this);
+ }
}
this.values.add(obj);
}
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java Thu Mar 6 05:33:44 2008
@@ -22,24 +22,14 @@
// based on work by Takayuki Takeuchi
/**
- * class representing a font descriptor for CID fonts.
+ * Class representing a font descriptor for CID fonts.
*
* Font descriptors for CID fonts are specified on page 227 and onwards of the PDF 1.3 spec.
*/
public class PDFCIDFontDescriptor extends PDFFontDescriptor {
/**
- * The language for the font
- */
- protected String lang;
-
- /**
- * The cid set stream
- */
- protected PDFStream cidSet;
-
- /**
- * create the /FontDescriptor object
+ * Create a /FontDescriptor object.
*
* @param basefont the base font name
* @param fontBBox the bounding box for the described font
@@ -56,31 +46,19 @@
super(basefont, fontBBox[3], fontBBox[1], capHeight, flags,
new PDFRectangle(fontBBox), italicAngle, stemV);
- this.lang = lang;
+ put("MissingWidth", new Integer(500));
+ if (lang != null) {
+ put("Lang", lang);
+ }
}
/**
* Set the CID set stream.
- * @param cidSet the pdf stream cotnaining the CID set
+ * @param cidSet the PDF stream containing the CID set
*/
public void setCIDSet(PDFStream cidSet) {
- this.cidSet = cidSet;
- }
-
- /**
- * Fill in the pdf data for this font descriptor.
- * The charset specific dictionary entries are output.
- * @param p the string buffer to append the data
- */
- protected void fillInPDF(StringBuffer p) {
- p.append("\n/MissingWidth 500\n");
- if (lang != null) {
- p.append("\n/Lang /");
- p.append(lang);
- }
if (cidSet != null) {
- p.append("\n/CIDSet /");
- p.append(this.cidSet.referencePDF());
+ put("CIDSet", cidSet);
}
}
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFCMap.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFCMap.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFCMap.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFCMap.java Thu Mar 6 05:33:44 2008
@@ -21,6 +21,8 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.Writer;
/**
* Class representing the CMap encodings.
@@ -395,15 +397,6 @@
}
/**
- * Add the contents of this pdf object to the PDF stream.
- */
- public void addContents() {
- StringBuffer p = new StringBuffer();
- fillInPDF(p);
- add(p.toString());
- }
-
- /**
* set the base CMap
*
* @param base the name of the base CMap
@@ -422,107 +415,20 @@
}
/**
- * Fill in the pdf string for this CMap.
- *
- * @param p the string buffer to add the pdf data to
+ * Creates the CMapBuilder that will build the CMap's content.
+ * @param writer a Writer to write the CMap's contents to
+ * @return the newly created CMapBuilder
*/
- public void fillInPDF(StringBuffer p) {
- writePreStream(p);
- writeStreamComments(p);
- writeCIDInit(p);
- writeCIDSystemInfo(p);
- writeVersionTypeName(p);
- writeCodeSpaceRange(p);
- writeCIDRange(p);
- writeBFEntries(p);
- writeWrapUp(p);
- writeStreamAfterComments(p);
- writeUseCMap(p);
- add(p.toString());
- }
-
- protected void writePreStream(StringBuffer p) {
- // p.append("/Type /CMap\n");
- // p.append(sysInfo.toPDFString());
- // p.append("/CMapName /" + name + EOL);
- }
-
- protected void writeStreamComments(StringBuffer p) {
- p.append("%!PS-Adobe-3.0 Resource-CMap\n");
- p.append("%%DocumentNeededResources: ProcSet (CIDInit)\n");
- p.append("%%IncludeResource: ProcSet (CIDInit)\n");
- p.append("%%BeginResource: CMap (" + name + ")\n");
- p.append("%%EndComments\n");
- }
-
- protected void writeCIDInit(StringBuffer p) {
- p.append("/CIDInit /ProcSet findresource begin\n");
- p.append("12 dict begin\n");
- p.append("begincmap\n");
- }
-
- protected void writeCIDSystemInfo(StringBuffer p) {
- p.append("/CIDSystemInfo 3 dict dup begin\n");
- p.append(" /Registry (Adobe) def\n");
- p.append(" /Ordering (Identity) def\n");
- p.append(" /Supplement 0 def\n");
- p.append("end def\n");
- }
-
- protected void writeVersionTypeName(StringBuffer p) {
- p.append("/CMapVersion 1 def\n");
- p.append("/CMapType 1 def\n");
- p.append("/CMapName /" + name + " def\n");
- }
-
- protected void writeCodeSpaceRange(StringBuffer p) {
- p.append("1 begincodespacerange\n");
- p.append("<0000> <FFFF>\n");
- p.append("endcodespacerange\n");
- }
-
- protected void writeCIDRange(StringBuffer p) {
- p.append("1 begincidrange\n");
- p.append("<0000> <FFFF> 0\n");
- p.append("endcidrange\n");
- }
-
- protected void writeBFEntries(StringBuffer p) {
- // p.append("1 beginbfrange\n");
- // p.append("<0020> <0100> <0000>\n");
- // p.append("endbfrange\n");
+ protected CMapBuilder createCMapBuilder(Writer writer) {
+ return new CMapBuilder(writer, this.name);
}
-
- protected void writeWrapUp(StringBuffer p) {
- p.append("endcmap\n");
- p.append("CMapName currentdict /CMap defineresource pop\n");
- p.append("end\n");
- p.append("end\n");
- }
-
- protected void writeStreamAfterComments(StringBuffer p) {
- p.append("%%EndResource\n");
- p.append("%%EOF\n");
- }
-
- protected void writeUseCMap(StringBuffer p) {
- /*
- * p.append(" /Type /CMap");
- * p.append("/CMapName /" + name + EOL);
- * p.append("/WMode " + wMode + EOL);
- * if (base != null) {
- * p.append("/UseCMap ");
- * if (base instanceof String) {
- * p.append("/"+base);
- * } else {// base instanceof PDFStream
- * p.append(((PDFStream)base).referencePDF());
- * }
- * }
- */
- }
-
+
+ /** {@inheritDoc} */
protected int output(OutputStream stream) throws IOException {
- fillInPDF(new StringBuffer());
+ StringWriter writer = new StringWriter();
+ CMapBuilder builder = createCMapBuilder(writer);
+ builder.writeCMap();
+ add(writer.getBuffer().toString()); //TODO Could be optimized by not buffering
return super.output(stream);
}
}
Propchange: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFConformanceException.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFDictionary.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFDictionary.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFDictionary.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFDictionary.java Thu Mar 6 05:33:44 2008
@@ -65,6 +65,12 @@
* @param value the value
*/
public void put(String name, Object value) {
+ if (value instanceof PDFObject) {
+ PDFObject pdfObj = (PDFObject)value;
+ if (!pdfObj.hasObjectNumber()) {
+ pdfObj.setParent(this);
+ }
+ }
if (!entries.containsKey(name)) {
this.order.add(name);
}
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFEncoding.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFEncoding.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFEncoding.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFEncoding.java Thu Mar 6 05:33:44 2008
@@ -20,12 +20,11 @@
package org.apache.fop.pdf;
// Java
-import java.util.List;
-import java.util.Map;
-import java.util.Iterator;
+import java.util.Collections;
+import java.util.Set;
/**
- * class representing an /Encoding object.
+ * Class representing an /Encoding object.
*
* A small object expressing the base encoding name and
* the differences from the base encoding.
@@ -34,90 +33,113 @@
*
* Encodings are specified in section 5.5.5 of the PDF 1.4 spec.
*/
-public class PDFEncoding extends PDFObject {
+public class PDFEncoding extends PDFDictionary {
- /**
- * the name for the standard encoding scheme
- */
+ /** the name for the standard encoding scheme */
+ public static final String STANDARD_ENCODING = "StandardEncoding";
+ /** the name for the Mac Roman encoding scheme */
public static final String MAC_ROMAN_ENCODING = "MacRomanEncoding";
-
- /**
- * the name for the standard encoding scheme
- */
+ /** the name for the Mac Export encoding scheme */
public static final String MAC_EXPERT_ENCODING = "MacExpertEncoding";
-
- /**
- * the name for the standard encoding scheme
- */
+ /** the name for the WinAnsi encoding scheme */
public static final String WIN_ANSI_ENCODING = "WinAnsiEncoding";
+ /** the name for the PDF document encoding scheme */
+ public static final String PDF_DOC_ENCODING = "PDFDocEncoding";
- /**
- * the name for the base encoding.
- * One of the three base encoding scheme names or
- * the default font's base encoding if null.
- */
- protected String basename;
-
- /**
- * the differences from the base encoding
- */
- protected Map differences;
+ /** the set of predefined encodings that can be assumed present in a PDF viewer */
+ private static final Set PREDEFINED_ENCODINGS;
+
+ static {
+ Set encodings = new java.util.HashSet();
+ encodings.add(STANDARD_ENCODING);
+ encodings.add(MAC_ROMAN_ENCODING);
+ encodings.add(MAC_EXPERT_ENCODING);
+ encodings.add(WIN_ANSI_ENCODING);
+ encodings.add(PDF_DOC_ENCODING);
+ PREDEFINED_ENCODINGS = Collections.unmodifiableSet(encodings);
+ }
/**
- * create the /Encoding object
+ * Create a new /Encoding object.
*
* @param basename the name of the character encoding schema
*/
public PDFEncoding(String basename) {
-
- /* generic creation of PDF object */
super();
- /* set fields using paramaters */
- this.basename = basename;
- this.differences = new java.util.HashMap();
+ put("Type", new PDFName("Encoding"));
+ if (basename != null) {
+ put("BaseEncoding", new PDFName(basename));
+ }
}
/**
- * add differences to the encoding
- *
- * @param code the first index of the sequence to be changed
- * @param sequence the sequence of glyph names (as String)
+ * Indicates whether a given encoding is one of the predefined encodings.
+ * @param name the encoding name (ex. "StandardEncoding")
+ * @return true if it is a predefined encoding
+ */
+ public static boolean isPredefinedEncoding(String name) {
+ return PREDEFINED_ENCODINGS.contains(name);
+ }
+
+ /**
+ * Creates and returns a new DifferencesBuilder instance for constructing the Differences
+ * array.
+ * @return the DifferencesBuilder
*/
- public void addDifferences(int code, List sequence) {
- differences.put(new Integer(code), sequence);
+ public DifferencesBuilder createDifferencesBuilder() {
+ return new DifferencesBuilder();
}
/**
- * {@inheritDoc}
+ * Sets the Differences value.
+ * @param differences the differences.
+ */
+ public void setDifferences(PDFArray differences) {
+ put("Differences", differences);
+ }
+
+ /**
+ * Builder class for constructing the Differences array.
*/
- public String toPDFString() {
- StringBuffer p = new StringBuffer(128);
- p.append(getObjectID()
- + "<< /Type /Encoding");
- if ((basename != null) && (!basename.equals(""))) {
- p.append("\n/BaseEncoding /" + this.basename);
+ public class DifferencesBuilder {
+
+ private PDFArray differences = new PDFArray();
+ private int currentCode = -1;
+
+ /**
+ * Start a new difference.
+ * @param code the starting code index inside the encoding
+ * @return this builder instance
+ */
+ public DifferencesBuilder addDifference(int code) {
+ this.currentCode = code;
+ this.differences.add(new Integer(code));
+ return this;
}
- if (!differences.isEmpty()) {
- p.append("\n/Differences [ ");
- Object code;
- Iterator codes = differences.keySet().iterator();
- while (codes.hasNext()) {
- code = codes.next();
- p.append(" ");
- p.append(code);
- List sequence = (List)differences.get(code);
- for (int i = 0; i < sequence.size(); i++) {
- p.append(" /");
- p.append((String)sequence.get(i));
- }
+
+ /**
+ * Adds a character name to the current difference.
+ * @param name the character name
+ * @return this builder instance
+ */
+ public DifferencesBuilder addName(String name) {
+ if (this.currentCode < 0) {
+ throw new IllegalStateException("addDifference(int) must be called first");
}
- p.append(" ]");
+ this.differences.add(new PDFName(name));
+ return this;
+ }
+
+ /**
+ * Creates and returns the PDFArray representing the Differences entry.
+ * @return the Differences entry
+ */
+ public PDFArray toPDFArray() {
+ return this.differences;
}
- p.append(" >>\nendobj\n");
- return p.toString();
}
-
+
/*
* example (p. 214)
* 25 0 obj
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFFactory.java?rev=634267&r1=634266&r2=634267&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFFactory.java (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/java/org/apache/fop/pdf/PDFFactory.java Thu Mar 6 05:33:44 2008
@@ -43,12 +43,14 @@
import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.fop.fonts.CIDFont;
+import org.apache.fop.fonts.CodePointMapping;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.FontDescriptor;
import org.apache.fop.fonts.FontMetrics;
import org.apache.fop.fonts.FontType;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.fonts.truetype.FontFileReader;
import org.apache.fop.fonts.truetype.TTFSubSetFile;
@@ -1182,6 +1184,7 @@
}
if (descriptor == null) {
+ //Usually Base 14 fonts
PDFFont font = new PDFFont(fontname, FontType.TYPE1, basefont, encoding);
getDocument().registerObject(font);
return font;
@@ -1190,30 +1193,11 @@
PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor);
- PDFFontNonBase14 font = null;
- if (fonttype == FontType.TYPE0) {
- /*
- * Temporary commented out - customized CMaps
- * isn't needed until /ToUnicode support is added
- * PDFCMap cmap = new PDFCMap(++this.objectcount,
- * "fop-ucs-H",
- * new PDFCIDSystemInfo("Adobe",
- * "Identity",
- * 0));
- * cmap.addContents();
- * this.objects.add(cmap);
- */
- font = (PDFFontNonBase14)PDFFont.createFont(fontname, fonttype,
- basefont, "Identity-H");
- } else {
-
- font = (PDFFontNonBase14)PDFFont.createFont(fontname, fonttype,
- basefont, encoding);
- }
+ PDFFont font = null;
+ font = (PDFFont)PDFFont.createFont(fontname, fonttype,
+ basefont, encoding);
getDocument().registerObject(font);
- font.setDescriptor(pdfdesc);
-
if (fonttype == FontType.TYPE0) {
CIDFont cidMetrics;
if (metrics instanceof LazyFont) {
@@ -1233,7 +1217,7 @@
(PDFCIDFontDescriptor)pdfdesc);
getDocument().registerObject(cidFont);
- PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics, "fop-ucs-H",
+ PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics.getCharsUsed(), "fop-ucs-H",
new PDFCIDSystemInfo("Adobe",
"Identity",
0));
@@ -1241,16 +1225,59 @@
((PDFFontType0)font).setCMAP(cmap);
((PDFFontType0)font).setDescendantFonts(cidFont);
} else {
- int firstChar = 0;
- int lastChar = 255;
- if (metrics instanceof CustomFont) {
- CustomFont cf = (CustomFont)metrics;
- firstChar = cf.getFirstChar();
- lastChar = cf.getLastChar();
+ PDFFontNonBase14 nonBase14 = (PDFFontNonBase14)font;
+ nonBase14.setDescriptor(pdfdesc);
+
+ SingleByteFont singleByteFont;
+ if (metrics instanceof LazyFont) {
+ singleByteFont = (SingleByteFont)((LazyFont)metrics).getRealFont();
+ } else {
+ singleByteFont = (SingleByteFont)metrics;
}
- font.setWidthMetrics(firstChar,
+ int firstChar = singleByteFont.getFirstChar();
+ int lastChar = singleByteFont.getLastChar();
+ nonBase14.setWidthMetrics(firstChar,
lastChar,
makeArray(metrics.getWidths()));
+
+ //Handle encoding
+ CodePointMapping mapping = singleByteFont.getCodePointMapping();
+ if (PDFEncoding.isPredefinedEncoding(mapping.getName())) {
+ font.setEncoding(mapping.getName());
+ } else {
+ CodePointMapping winansi = CodePointMapping.getMapping(
+ CodePointMapping.WIN_ANSI_ENCODING);
+ PDFEncoding pdfEncoding = new PDFEncoding(winansi.getName());
+ PDFEncoding.DifferencesBuilder builder
+ = pdfEncoding.createDifferencesBuilder();
+ int start = -1;
+ String[] winansiNames = winansi.getCharNameMap();
+ String[] charNameMap = mapping.getCharNameMap();
+ for (int i = 0; i < 256; i++) {
+ String wac = winansiNames[i];
+ String c = charNameMap[i];
+ if (!wac.equals(c)) {
+ if (start != i) {
+ builder.addDifference(i);
+ start = i;
+ }
+ builder.addName(c);
+ start++;
+ }
+ }
+ pdfEncoding.setDifferences(builder.toPDFArray());
+ font.setEncoding(pdfEncoding);
+
+ /* JM: What I thought would be a necessity with custom encodings turned out to
+ * be a bug in Adobe Acrobat 8. The following section just demonstrates how
+ * to generate a ToUnicode CMap for a Type 1 font.
+ PDFCMap cmap = new PDFToUnicodeCMap(mapping.getUnicodeCharMap(),
+ "fop-ucs-H",
+ new PDFCIDSystemInfo("Adobe", "Identity", 0));
+ getDocument().registerObject(cmap);
+ nonBase14.setToUnicode(cmap);
+ */
+ }
}
return font;
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org